← Back to blog

How to Accept Crypto Payments on Your Website

· 4 min read
guide integration

So you want to accept crypto on your website. Good news: it’s simpler than you think. Bad news: most guides overcomplicate it. Here’s the no-fluff version.

What You Actually Need

Forget running your own node or managing wallets manually. A crypto payment gateway handles the hard parts: generating payment addresses, monitoring blockchains for confirmations, and converting tokens.

You need three things:

  1. A wallet address to receive funds
  2. A payment gateway with an API
  3. About 20 minutes

Step 1: Choose Your Settlement Currency

This is the first decision that matters. Do you want to receive ETH? USDC? A mix?

Most merchants go with stablecoins (USDC, USDT, DAI) because the value doesn’t swing 10% overnight. With MutoPay, your customers can pay with any token, but you always receive your chosen stablecoin. Problem solved before it starts.

Step 2: Create a Channel and Get Your API Key

In your MutoPay dashboard, go to Settings → Channels and click + New channel. Give it a name (e.g. “My Website”) and optionally set a webhook URL. Your API key (ep_... prefix) is shown once — copy it.

This key identifies your channel and authenticates your API calls. Each channel has its own key, webhook URL, and can have its own settlement destination.

Step 3: Create a Payment

One API call. That’s it.

curl -X POST https://mutopay.com/api/payments \
  -H "X-API-Key: ep_your_channel_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_usd": 50.00,
    "description": "Order #1234 — Blue Widget",
    "external_id": "order_1234",
    "callback_url": "https://yoursite.com/order/1234/complete"
  }'

You get back a payment object with an id. Redirect your customer to mutopay.com/pay/{id}.

Fields you can set:

FieldDescription
amount_usdAmount in USD
amountAmount in another currency (use with currency)
currencyCurrency code if not USD (e.g. EUR, GBP)
descriptionShown to the customer on the payment page
external_idYour internal reference (e.g. order ID)
callback_urlWhere to redirect the customer after payment
metadataArbitrary JSON for your own use
expires_in_minutes15 to 10080 (7 days); default is 60

Use either amount_usd or amount + currency, not both.

Step 4: Handle the Webhook

When the payment completes (or fails, or expires), MutoPay sends a POST to your channel’s webhook URL. The payload tells you everything:

{
  "event": "payment.completed",
  "payment_id": "pay_abc123",
  "status": "completed",
  "amount_usd": 50.00,
  "currency": "USD",
  "dest_token": "USDC",
  "dest_chain_id": "137",
  "dest_amount": "50000000",
  "dest_decimals": 6,
  "external_id": "order_1234",
  "tx_hash": "0xabc...",
  "completed_at": "2026-04-12T14:30:00Z",
  "timestamp": "2026-04-12T14:30:01Z"
}

Verify the signature. Every webhook includes an X-MutoPay-Signature header with an HMAC-SHA256 hash of the raw JSON body, signed with your channel’s webhook secret (visible in your dashboard). Format: sha256=<hex>.

Parse the settlement amount. dest_amount is in raw token units. Divide by 10^dest_decimals to get the human-readable figure. In the example above: 50000000 / 10^6 = 50.00 USDC.

Webhook events: payment.completed, payment.failed, payment.expired, payment.underpaid, payment.kyc_required, payment.needs_manual_check.

Failed deliveries are retried 5 times with exponential backoff (1 min → 5 min → 30 min → 2 hours → 12 hours).

Step 5: Show the Customer a Payment Page

You have two options:

Redirect — send the customer to the hosted payment page at mutopay.com/pay/{id}. They select their token, connect their wallet, and pay. Zero frontend work on your end. Mobile customers see a QR code for easy deposit.

Poll — use the payment ID to build your own UI. Call GET /api/payments/{id}/status for lightweight status updates.

Most merchants start with the redirect approach and customize later.

Common Questions

What if the customer pays with a token on a different chain? The gateway handles cross-chain bridging automatically. Customer pays with ARB on Arbitrum, you receive USDC on Polygon. They don’t need to think about it.

What about refunds? Crypto payments are irreversible at the protocol level. Handle refunds by sending a separate transaction back to the customer’s wallet.

How long do payments take? Direct stablecoin transfers confirm in seconds. Cross-chain swaps typically settle in under 2 minutes.

What’s the fee? MutoPay charges 0.25% per transaction. No monthly fees, no minimums.

What chains are supported? Ethereum, Polygon, Arbitrum, Base, Optimism, Avalanche, BSC, TON, Solana, and Tron. Customers can pay with 1,000+ tokens across all 10 chains.

What’s Next

Once you’re processing payments, you’ll want to:

  • Monitor payments in your merchant dashboard
  • Test your webhook integration from Settings → Channels → Test Webhook
  • Add a Pay Me link for tips and open-ended payments
  • Explore channel management for multi-brand or multi-client setups

The whole integration takes about 20 minutes for a developer who’s done API work before. No blockchain knowledge required.