The one difference everything else follows from
A stablecoin is a token engineered to track a reference currency — for halfin's purposes, the US dollar. One USDT or one USDC is meant to be worth one dollar, and in normal conditions it stays close. Bitcoin is the opposite by design: a fixed-supply asset whose price floats freely against the dollar and moves on its own schedule, sometimes by a meaningful percentage within the span of a checkout.
That is the whole comparison in one sentence — but it is not the whole decision, because how halfin invoices work changes what the difference costs you. The instinct is to assume Bitcoin's volatility makes it risky to accept. It can be, if you quote a token amount and reconcile loosely. It is not, if you anchor the invoice to a fiat figure and let the rate lock at activation. So before comparing the assets, it helps to separate two questions that often get tangled: what value settles to your balance, and which token the customer hands over to get there.
The token the customer pays in is a payer-habit and network-cost question; the value you book is a pricing question, and halfin answers it the same way regardless of which token shows up — by pinning the rate when the invoice goes live. Keep that split in mind and the stablecoin-versus-Bitcoin choice gets much smaller than it first appears.
Price stability: what actually settles to your balance
Start with the figure you care about: the value that lands in your ledger. A stablecoin payment is intuitive — bill the equivalent of 100 dollars, the customer sends roughly 100 USDC, and the dollar value barely budges between send and confirm because the token itself is pegged near a dollar. There is almost no gap between "amount shown" and "amount worth."
Bitcoin looks scarier only if you quote in BTC. If you put "pay 0.0011 BTC" on the invoice and the price drifts during the payment window, the dollar value of that exact quantity drifts with it, and you can end up short against what you meant to charge. This is the volatility people warn about, and it is real for a naive token-denominated request.
halfin removes that gap by anchoring the invoice to fiat and locking the rate at activation. You state the amount in USD or EUR; halfin computes the payable token amount — whether that token is USDC or BTC — and freezes it for the life of the invoice, alongside an expiry. If the customer pays a Bitcoin invoice inside the window, the BTC quantity they were shown is the quantity that settles to your billed dollar figure. If the window lapses, the invoice expires rather than silently re-pricing against a newer rate, and you re-issue at the current rate on your terms. The net effect: with a fiat-anchored invoice, the booked value of a Bitcoin payment is as predictable as a stablecoin one — the volatility lives inside the locked window, and the lock plus the expiry contain it.
- Stablecoin (USDT/USDC): token value ≈ dollar value, so amount-shown and amount-worth barely diverge.
- Bitcoin quoted in BTC: dollar value of a fixed BTC quantity moves with the market during the window.
- Fiat-anchored invoice: rate locks at activation for either asset — the booked figure is the fiat amount you billed.
- Lapsed quote expires instead of re-pricing, so you never honor a stale Bitcoin rate by accident.
Fee character: a chain property, not a halfin price
Network fees are a property of the chain a payment travels on, not a halfin charge, and they are part of the practical difference between accepting a stablecoin and accepting Bitcoin — because the two often ride different rails. A stablecoin is not one network: USDT settles on Tron, Ethereum, or Solana, and USDC on Ethereum, Base, or Solana, each with its own fee feel. Bitcoin has its own fee market driven by block space demand, independent of any of those.
What this means for you is qualitative, not a number we can quote: fees rise and fall with congestion on each chain, and the same dollar amount can cost the customer a different amount depending on the rail they pick. For small-ticket payments that friction is felt more sharply by the payer, which is part of why payers gravitate toward low-cost stablecoin networks for everyday amounts. For larger or less frequent payments — and for customers who hold value in Bitcoin — the network cost is a smaller fraction of the transfer and matters less.
Because the customer chooses the asset and network on a halfin invoice, you do not have to forecast this. The table below summarizes the practical character of each option — read "fee feel" as a relative tendency, never a committed rate.
| Option | Networks | Price behavior | Fee feel (qualitative) |
|---|---|---|---|
| USDT | Tron (TRC-20), Ethereum (ERC-20), Solana | Pegged near the dollar | Light on Tron / Solana; heavier on Ethereum when congested |
| USDC | Ethereum (ERC-20), Base, Solana | Pegged near the dollar | Light on Base / Solana; heavier on Ethereum mainnet when busy |
| Bitcoin (BTC) | Bitcoin | Floats freely against fiat | Own fee market driven by block-space demand |
Payer habits: which customer reaches for which asset
The asset your customers prefer is at least as decisive as any technical property, because an option nobody uses is dead weight on the checkout. Stablecoins are the default for people who treat crypto as a way to move dollars: freelancers and contractors invoicing internationally, traders moving balances between venues, and anyone who wants the amount they send to equal the amount they owe without watching a chart. For these payers, USDT on Tron and USDC on Solana or Base are muscle memory.
Bitcoin payers are a different cohort. Some hold the bulk of their crypto net worth in BTC and prefer to spend from it directly rather than convert first. Some are paying from cold storage or a BTC-only wallet. Some simply identify with Bitcoin and will choose it when offered. They tend to skew toward larger or more deliberate payments rather than rapid small-ticket flows, which lines up neatly with Bitcoin's fee character.
The practical read: if your audience is payments-oriented and cost-sensitive — marketplaces, SaaS, affiliate payouts, everyday e-commerce — stablecoins will carry most of the volume. If your audience includes Bitcoin-native holders, or you sell higher-ticket items where a BTC payer is plausible, offering Bitcoin captures customers a stablecoin-only checkout would turn away.
- Stablecoin-leaning: contractors, traders, marketplaces, SaaS, affiliates, cost-sensitive everyday payments.
- Bitcoin-leaning: BTC-native holders, cold-storage spenders, higher-ticket or more deliberate purchases.
- Offering only stablecoins quietly turns away Bitcoin holders; offering only BTC adds volatility friction for dollar-movers.
- The asset is the customer's choice on a halfin invoice — you decide which to make available, not which they must use.
You don't have to choose: a fiat-anchored invoice does it for you
The framing of "stablecoin versus Bitcoin" assumes you pick one and build a flow around it. You don't. A single halfin invoice can present multiple supported assets and let the customer settle in whichever one they hold — USDT on Tron, USDC on Base, or BTC on Bitcoin — while the fiat anchor stays identical. There is no separate integration per asset: you expose the assets you want to accept on one invoice and reconcile against one dollar figure.
The call below is the same create call you would make for any invoice — note that it names a fiat amount and currency, not a token. Because the invoice is anchored to USD and the rate locks at activation, the customer can settle it in a stablecoin or in Bitcoin and your booked value is unchanged. Monetary values are strings end to end, and the idempotency_key is a snake_case field in the request body so a retried create never produces a duplicate invoice.
# Create a fiat-anchored invoice. The customer can settle in a stablecoin
# (USDT / USDC) or in Bitcoin — the booked value is the fiat amount below.
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": "100.00",
"fiat_currency": "USD",
"deferred": true,
"description": "Order 4821",
"idempotency_key": "00000000-0000-4000-8000-000000000010"
}'
# halfin locks the rate at activation and pins the payable token amount for
# whichever asset the customer chooses. Track the result via signed webhook
# events — verify the HMAC over the raw bytes before acting. See
# docs.thehalfin.com for the full request and response schema.When fixed-asset pricing makes sense instead
Fiat-anchoring is the right default for most businesses, but it is not the only mode. halfin also supports a fixed-asset invoice: you state an amount and a crypto currency directly — say, a specific quantity of USDT — and that token amount is what the customer pays, with no fiat conversion in the middle. It fits when your price genuinely lives in the asset.
Two common cases. First, you natively think in a stablecoin: your catalog and accounting are already denominated in USDT or USDC, so anchoring to fiat would just add a round-trip you don't need — quote the stablecoin amount directly. Second, you are accepting a deposit or settlement where the counterparty agreed to a token amount up front. For Bitcoin, fixed-asset pricing is rarer for storefront checkout precisely because BTC's float reintroduces the volatility a fiat anchor removes — but it is the right tool when a contract is denominated in BTC itself.
The decision rule is short: if your books are in dollars, anchor to fiat and let the customer pick the asset; if your books are genuinely in a token, price in that token. Either way the lifecycle, confirmation handling, and webhooks are the same — only which figure is the source of truth changes.
Settlement is the same for both assets
Whichever asset settles your invoice, the mechanics downstream are identical, so accepting both adds no real operational complexity. Crediting is reorg-aware and respects each chain's confirmation threshold: halfin waits for the network-appropriate number of confirmations before marking an invoice paid, and a chain reorganization that unwinds a transaction is reflected rather than ignored. Bitcoin and a stablecoin differ in how long that takes and how many confirmations the chain warrants, but a "paid" invoice means the same thing for both.
Underpaid and overpaid outcomes are first-class for both. A customer who sends slightly too little against a Bitcoin invoice produces an underpaid state with the shortfall recorded; an overpayment in either asset is recorded against the invoice so the excess stays visible rather than stranded. And both flow through the same signed webhook events — invoice.confirming, invoice.paid, invoice.overpaid, invoice.underpaid, invoice.expired — so your backend handles a Bitcoin payment and a USDC payment through one code path. Verify the HMAC signature over the raw request bytes before you act on any of them.