How to Sell Digital Goods for Crypto

A practical guide to selling license keys, downloads, courses and other digital products for crypto, with automatic delivery and fewer support tickets.

06.11.20269 хв читання
License key card with a download button and delivered badge, in front of an e-book and a video course

To sell digital products for crypto, you need three things: a place to take the order (a website, a Telegram bot or a simple invoice link), a crypto payment gateway that creates an invoice and confirms the payment, and automatic delivery that sends the key, file or access the moment the payment is confirmed. Price in USD, let customers pay in USDT or another coin, and deliver only on a verified webhook.

Digital goods and crypto fit well together. Delivery is instant and global, the customer often already holds crypto, and there are no chargebacks months after a license key has been used. The hard part is not taking the payment. It is delivering reliably and handling customers who pay too little, too late or on the wrong network.

This guide walks through the setup for license keys, downloads, courses, accounts, game items and other digital products.

Which digital products you can sell for crypto

Typical digital goods sold for crypto:

  • software licenses and activation keys

  • downloadable files: templates, presets, e-books, audio, fonts

  • online courses and membership access

  • game items, in-game currency and top-ups

  • gift cards and vouchers

  • API credits and SaaS plans (see renewals below)

Before you start, check two things. First, you need the right to sell what you sell: resold keys and accounts often break the publisher's terms. Second, check the tax rules in your country and your customers' countries. Digital goods are often subject to VAT or sales tax wherever the buyer is, regardless of the payment method. This is general information, not tax advice.

Step 1: choose where customers place the order

ChannelBest forHow payment works
Website on a CMS (WooCommerce and others)A catalog with many productsA plugin adds crypto as a payment method at checkout
Custom website or appYour own checkout and delivery logicYour backend creates invoices through the API
Telegram botAudiences that live in TelegramThe bot creates an invoice and sends the payment link
Invoice linkA few products, or sales over chat and social mediaYou create an invoice and send the link

If you already run WooCommerce, the quickest route is a plugin; our WooCommerce crypto payments guide covers setup. For a bot, see how to accept crypto payments in a Telegram bot. For a custom site, the general flow is in how to accept USDT payments on your website.

Step 2: price in USD and choose coins

Price your products in USD, not in a coin. A $19 course stays $19, and the customer picks the coin and network on the hosted payment page.

For digital goods, a good starting set:

  • USDT on TRC20, BEP20, TON and Solana: stable value, cheap networks for small baskets

  • USDC for customers who prefer it

  • BTC and LTC for customers who hold them

  • ETH on Base or Arbitrum, where fees are lower than on Ethereum mainnet

Small baskets need cheap networks. If your average order is $5–15, the customer's network fee and exchange withdrawal fee can be a noticeable share of the price on expensive networks. Supported coins and networks are listed on the accept USDT page.

Step 3: deliver automatically on a verified webhook

This is the core of selling digital goods. The goal: the customer pays, and within a minute they have what they bought, without you touching anything.

The flow

  1. The customer clicks "Buy". Your backend creates an order with status pending and creates an invoice with the gateway, passing your order ID.

  2. The customer pays on the hosted payment page, which shows a QR code, the amount and a countdown.

  3. After the required network confirmations, the gateway sends a webhook invoice.paid with data.status of PAID or OVERPAID.

  4. Your server verifies the signature, finds the order, marks it paid and delivers: it reserves a license key, generates a download link or grants course access.

  5. The customer is redirected to your success page, which shows the result and says it was sent by email too.

Creating the invoice

Zypher invoices are created with POST /api/v1/invoice. The request is signed: X-API-Sign is the hex HMAC-SHA256 of the exact JSON body, using your API secret. In Python:

import hashlib, hmac, json, os, requests

API_KEY = os.environ["ZYPHER_API_KEY"]
API_SECRET = os.environ["ZYPHER_API_SECRET"]

body = json.dumps({
    "fiatAmount": "19.00",
    "fiatCurrency": "USD",
    "orderId": "order-10452",
}, separators=(",", ":"))

sign = hmac.new(API_SECRET.encode(), body.encode(), hashlib.sha256).hexdigest()

resp = requests.post(
    "https://zypher.exchange/api/v1/invoice",
    data=body,  # send exactly the bytes you signed
    headers={"Content-Type": "application/json",
             "X-API-Key": API_KEY, "X-API-Sign": sign},
)
invoice = resp.json()
# store invoice id next to your order, then redirect the customer to the payment page

Send exactly the string you signed. If you sign one JSON string and let your HTTP library re-serialize the object, the signature will not match. The response format and field reference are in the API docs.

Verifying the webhook and delivering

The webhook carries X-Webhook-Signature, the hex HMAC-SHA256 of the raw request body with your API secret. Verify it on the raw bytes before parsing:

import hashlib, hmac, json

def handle_webhook(raw_body: bytes, signature: str):
    expected = hmac.new(API_SECRET.encode(), raw_body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature or ""):
        return 401
    payload = json.loads(raw_body)
    if payload["event"] != "invoice.paid":
        return 200
    data = payload["data"]
    if data["status"] in ("PAID", "OVERPAID"):
        deliver_once(data)  # idempotent: does nothing if this invoice was already delivered
    return 200

Make delivery idempotent

Failed webhook deliveries are retried, up to five attempts, so your handler may see the same invoice twice. Your deliver_once function should:

  • look up the order by invoice ID in a database transaction

  • exit if the order is already delivered

  • reserve the key (mark it as sold to that order) in the same transaction

  • send the email after the transaction commits

This also protects your key stock: two parallel webhook calls cannot hand out two keys for one order.

Delivery patterns by product type

License keys

Keep a pool of keys per product in your database with a status: available, reserved, sold. Reserve on payment, show the key on the success page and send it by email. Alert yourself when stock falls below a threshold, so you do not sell a key you do not have. If the pool is empty when payment arrives, mark the order as "paid, awaiting key" and email the customer a realistic time frame.

Downloads

Do not email a permanent public link. Generate a signed, expiring download URL (for example valid 24–72 hours, with a limited number of downloads) and let the customer re-generate it from their order page.

Courses and memberships

Grant access to the account rather than sending a file. If the customer has no account yet, create one from the email on the order and send a login link.

Game items and top-ups

Ask for the in-game ID before payment and validate it, because a top-up to the wrong player ID is hard to reverse. Show the ID again on the payment confirmation page.

Edge cases that cost money

Underpayment

Customers paying from an exchange often lose the withdrawal fee from the amount. On Zypher, 98% or more of the invoice amount counts as paid. Below that, the invoice is UNDERPAID, the customer can send the remainder to the same address, and partial payments add up. Do not deliver on UNDERPAID. Do tell the customer how much is missing.

Late payment

A coin-priced invoice expires after 30 minutes. A USD-priced one gives the customer 60 minutes to pick a coin and then 30 minutes to pay. A payment that arrives up to 30 minutes after expiry can still be matched. Beyond that, handle it manually: find the transaction, confirm the amount and deliver or refund.

Overpayment

Anything above 102% is marked OVERPAID. The webhook still arrives, so deliver the product. Then decide on a policy for the extra: refund it if it is large, or offer store credit.

Wrong network or wrong coin

These payments do not reach the invoice. Your support team should know what can and cannot be recovered; the details depend on the networks involved.

Refunds

Crypto payments have no chargebacks, but you will still need refunds for broken keys, duplicate purchases or goodwill. Write a refund policy for digital goods and show it at checkout. Then:

  1. Ask the customer for a refund address and network in writing.

  2. Refund in the coin they paid, or in USDT at the USD value. State which in your policy.

  3. Refund from your balance with a normal withdrawal, which pays the network fee.

  4. Revoke or blacklist the key or access you delivered.

Fees and margins

Digital goods often have thin per-unit costs but small tickets, so the processing fee matters. Zypher charges 1% per paid invoice on the Start tier, falling to 0.75% from $10k of 30-day volume and lower above that, with no setup or monthly fees. Other gateways charge from about 0.4% to 3%; we compared them in crypto payment gateway fees compared.

Launch checklist

  • Products priced in USD; coins and cheap networks enabled

  • Invoice created server-side with your order ID

  • Webhook signature verified on the raw body

  • Delivery only on PAID or OVERPAID, never on redirect

  • Delivery idempotent, key reservation in a transaction

  • Low-stock alert for key pools

  • Expiring download links

  • Refund policy visible at checkout

  • One real low-value purchase tested end to end

Zypher has a dedicated digital goods solution page with an overview of this setup. Opening a store takes about a minute and needs no documents: sign up.

FAQ

Can I sell digital products for crypto without a website?

Yes. You can create an invoice for each order and send the payment link in a chat, by email or on social media. A Telegram bot is another option if your audience is there. Automatic delivery still needs a small backend that receives the payment webhook.

How do I deliver license keys automatically after a crypto payment?

Keep keys in a database, and reserve one when a signed invoice.paid webhook arrives with status PAID or OVERPAID. Show the key on the success page and send it by email. Make the handler idempotent so a repeated webhook does not hand out a second key.

What happens if a customer underpays for a digital product?

On Zypher, a payment of at least 98% of the amount counts as paid. Below that, the invoice is marked underpaid, and the customer can send the remainder to the same address. Deliver only once the invoice is paid.

Can customers get a chargeback on a crypto purchase?

No. A confirmed crypto payment cannot be reversed by the customer's bank. You still need a refund policy for broken keys or mistakes, and you send refunds as a normal withdrawal.

Which crypto should I accept for digital goods?

USDT is a good default because its value is stable. Offer it on cheap networks such as TRC20, BEP20, TON or Solana, especially for small orders. Add BTC, LTC and USDC for customers who prefer them.

Do I have to pay tax on digital goods sold for crypto?

Usually the same rules apply as for any other sale, and digital goods often carry VAT or sales tax based on the buyer's location. Rules differ by country. Check with a local accountant.

How to Sell Digital Products for Crypto (2026 Guide) | Zypher