Use case

Accept crypto payments in your online store

You already have a store, a checkout, and an order table. You want to add "pay with crypto" next to the card button without rebuilding any of that. The shape of it is small: when the customer picks crypto, you create an invoice for the order total, send them to a hosted page that handles every wallet and network detail, and you mark the order paid only when a signed webhook tells you the money has actually settled on-chain. This page is about that one job — the wiring between your store's checkout and a confirmed crypto payment.

01

The job: one more payment option, not a new order system

Most "accept crypto" integrations fail in one of two directions. Either they bolt a widget onto the page that shows a raw address and hopes the customer sends the right amount on the right chain, or they ask your team to learn block confirmations, address formats, and reorg behaviour for every network you want to take. Neither is what a store wants. A store wants crypto to behave like every other payment method it already has: the customer pays, the order flips to paid, fulfilment runs, finance reconciles.

The trick is to treat a crypto payment as an order event and keep the on-chain machinery off your side. You do three things and nothing more: create an invoice tied to the order, redirect the customer to a hosted page, and react to a signed webhook. Your order table, your inventory hold, and your fulfilment logic stay exactly as they are — the crypto payment slots into the same "paid" transition a card payment already drives.

What you are deliberately not building: a wallet-connect UI, QR generation, per-chain address rotation, a confirmation watcher, or a polling loop that has to survive a customer refreshing the page on a flaky phone. That surface lives at checkout.thehalfin.com, and it is the same surface for every store regardless of platform. There is no official CMS plugin — a custom store and a popular storefront wire the same REST API and the same hosted checkout the same way.

02

The flow, step by step

Here is the whole integration, in order. Each step maps onto something your store already does for cards, so you are adding a branch, not a parallel system.

Price in the currency your catalogue is already in. You create the invoice with a fiat amount — USD, EUR, whatever your prices use — and halfin computes the payable crypto amount from the live rate. That rate locks when the invoice activates and an expiry is stamped, so a customer who opens the page and pays a few minutes later owes the exact amount they were shown. A moving market does not quietly turn a $120 order into an underpayment.

Then the redirect is cosmetic and the webhook is authoritative. A customer can pay and close the tab before the success redirect ever fires; the signed webhook still arrives, and that is what should flip the order to paid. Build your store so the success page is a nicety and the webhook is the database write.

  • Customer picks "pay with crypto" at your checkout.
  • Your server creates an invoice for the order total, anchored in your catalogue currency, with the order id as the idempotency key.
  • You redirect the customer to the hosted checkout URL returned in the response.
  • The customer chooses a network they hold funds on, sees the exact amount, a QR code, and the deposit address; halfin watches the chain and shows live status.
  • halfin applies the per-chain confirmation threshold and credits the payment in a reorg-aware way.
  • Your server receives an HMAC-signed webhook — verify the signature, then mark the order paid and release fulfilment.
03

Reconciling orders from webhooks, not redirects

The single most important habit for a store integration is to drive your order state from webhooks. The customer's browser is unreliable — tabs close, connections drop, redirects get blocked — but the webhook is a server-to-server message that arrives whether or not the customer ever lands back on your success page. Treat it as the source of truth and your reconciliation stops depending on the customer doing the polite thing.

Tie each invoice to its order with the idempotency key. Passing your own order id as the idempotency key on the create call means a retried request — a double-click, a network blip, a queue redelivery — returns the same invoice instead of minting a second one for the same order. When the webhook lands, you match it back to the order it belongs to and you never have two invoices fighting over one cart.

Verify the signature before you act. Every webhook carries an HMAC signature; you recompute it over the raw body with your signing secret and compare before you trust a single field. An unverified payload is just an HTTP request anyone could have sent, and acting on it would let a forged "invoice.paid" release goods for free. The canonical events a store cares about are below; the exact envelope and signing scheme are documented at docs.thehalfin.com.

Webhook eventWhat happened on-chainWhat the store does
invoice.confirmingThe invoice went live; the rate is locked and the payment window is open.Optionally record that the order is awaiting payment; do not fulfil yet.
invoice.paidPayment confirmed to the per-chain threshold; the billed amount settled.Verify the signature, mark the order paid, release fulfilment.
invoice.underpaidA deposit arrived but fell short of the expected amount.Hold the order; request a top-up or settle partially per your policy.
invoice.overpaidThe deposit exceeded the expected amount.Fulfil the order; reconcile the excess, refund it if your policy says so.
invoice.expiredThe window elapsed before a sufficient payment arrived.Leave the order unpaid; re-issue at the current rate if the customer returns.
04

Why a confirmed crypto payment is final

A card payment can be reversed weeks after you have shipped. For a store selling digital goods, top-ups, downloads, or anything fulfilled quickly, a chargeback usually means the product is gone and the money is clawed back, plus a dispute fee and a hit to the acquirer scorecard that can quietly raise your costs.

A crypto payment confirmed through halfin does not work that way. Once a payment is credited under the chain's confirmation threshold, it has settled on-chain and there is no issuer-initiated reversal. That removes a whole category of after-the-fact fraud from the store. It also changes how you think about returns: because nothing forces a reversal on you, refunds are a deliberate choice you make — you return funds through the refund flow against the original invoice, on your own terms, rather than reacting to a dispute you cannot decline.

This is the reason digital-goods sellers and stores that card acquirers treat as high-risk reach for crypto first. It is not a discount on payments — pricing is a separate conversation — it is a different risk profile, where the store is no longer exposed to the long tail of card disputes on goods that are already delivered.

05

What you settle in, after the sale

The customer pays in whatever asset they hold on a network you enable; what lands in your halfin balances is your decision to shape. Stablecoins are the common case for a store because both sides know the dollar value will not move between checkout and confirmation, but a customer can also pay in a native asset like BTC, ETH, or SOL.

Once payments accrue to your balances, balance conversion handles consolidation — automatically on a policy you set, or manually when you want to fold a spread of incoming assets into the one stablecoin you keep reserves in. A store that takes USDT, USDC, and the odd BTC payment does not have to manage each balance by hand. The networks and assets below are the real on-chain gates; there is no placeholder option on the checkout that quietly does nothing.

NetworkNative assetStablecoins on this network
BitcoinBTC
EthereumETHUSDT (ERC-20), USDC (ERC-20)
BaseETHUSDC
ArbitrumETH
Polygonnative gas token
BNB Smart ChainBNB
TronTRXUSDT (TRC-20)
XRP LedgerXRP
SolanaSOLUSDT (SPL), USDC (SPL)
06

The create call your checkout makes

The store side of the integration is one authenticated POST. You send the order total as a fiat amount and currency; halfin pins the payable crypto amount at activation and returns an invoice with a hosted checkout URL you redirect the customer to. Amounts are strings end to end — never floats — and the currency is your fiat anchor, not a crypto code.

Pass your order id as the idempotency key so a retried request returns the same invoice instead of creating a duplicate. Then wait for the signed webhook before you mark the order paid. The full request and response schema, and the webhook signing scheme, live at docs.thehalfin.com.

curl -X POST https://api.thehalfin.com/api/v1/invoices \
  -H "X-API-Key: $HALFIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_fiat": "120.00",
    "fiat_currency": "USD",
    "description": "Order #58213",
    "idempotency_key": "order-58213"
  }'

# The fiat amount anchors the order. The customer settles in the crypto
# asset they pick on the hosted checkout page returned in the response.
# Redirect them there, then verify the signed invoice webhook before you
# mark the order paid. See docs.thehalfin.com for the full schema.