Native BTC on the base layer — what you are actually taking
When a customer pays this invoice, real bitcoin moves on the Bitcoin blockchain. There is no bridge, no swap, and no wrapped token standing in for BTC on a faster chain. The payer sends from whatever wallet they already trust, the transaction is mined into a Bitcoin block, and halfin's Bitcoin gate watches that chain for it. Because it is the base layer, the customer is never asked to leave their tools or trust a representation of bitcoin issued somewhere else — which is exactly why self-custody payers reach for it.
Bitcoin is also the asset with the least ambiguity about what it is: one BTC, one Bitcoin network, no token contract to verify and no second issuer to vet. The trade-off is deliberate settlement. Blocks are mined roughly every ten minutes, so a Bitcoin payment is not instant the way a stablecoin on a fast chain is. halfin's role on this rail is to make that wait legible rather than a black box — the payment moves through a visible sequence of states, and only the final one should trigger fulfilment.
If your customers also hold dollar-denominated stablecoins or pay from other chains, BTC is one rail among several you can offer on the same invoice — but this page stays narrow on purpose: accepting native bitcoin, well, on the network it was minted on.
Confirmations and reorg-aware crediting
A Bitcoin transaction is not final the instant it broadcasts. It waits in the mempool, gets mined into a block, then accumulates confirmations as more blocks stack on top. Early on, the chain can still reorganize: a competing block wins and a transaction that looked settled is unwound. Crediting too eagerly on that early signal is how merchants get burned.
halfin waits for the per-chain confirmation threshold before it marks a Bitcoin payment as paid, and the crediting is reorg-aware — if the chain reorganizes and undoes a transaction halfin was tracking, that is reflected rather than ignored. You do not implement confirmation counting, mempool watching, or reorg handling yourself; that logic lives in the Bitcoin gate. The number you see as settled is one that actually held on the canonical chain.
Practically, treat the early states as in-flight, not done. The table below is the shape of a single BTC payment as your integration observes it — through the dashboard, the REST API, or a signed webhook. The only state that should release goods is the settled one.
| State | What is happening on the Bitcoin network | What you should do |
|---|---|---|
| Awaiting payment | Invoice is live, the rate is locked, and the gate is watching for an incoming BTC transaction before the invoice expires. | Show the BTC address, the exact amount, and the countdown. |
| Payment seen | A matching transaction has appeared in the mempool but is not yet mined or not yet sufficiently confirmed. | Tell the customer the payment is in flight. Do not release goods. |
| Confirming | The transaction is mined and confirmations are accumulating toward the Bitcoin threshold. | Keep waiting — crediting is reorg-aware and not yet final. |
| Paid | The confirmation threshold is met; the billed amount settles to your balance. | Fulfil the order and reconcile against the fiat figure you billed. |
| Expired | The invoice window elapsed before a sufficient payment arrived. | Re-issue at the current rate if the customer still wants to pay. |
Three ways to take a BTC payment
How you collect bitcoin depends on the flow. Billing a known customer for a known amount is one shape; needing a standing place for value to land is another. halfin gives you the same Bitcoin gate underneath three surfaces, so you pick the one that fits instead of rebuilding the on-chain plumbing each time. Each option produces a Bitcoin address and an expected amount — the difference is lifecycle.
An invoice is a one-time, rate-locked request with an expiry. A static deposit address is a persistent place to receive bitcoin that does not expire. Hosted checkout is a halfin-rendered page wrapped around an invoice so you have nothing to build yourself. Most businesses use invoices for sales and a static address for top-ups, deposits, or anything that is not a single priced order.
- Invoicing — bill in your own currency (USD, EUR) and let the customer pay the equivalent in BTC. The rate locks when the invoice activates, so the amount you book never drifts while the customer fetches their wallet. Underpaid and overpaid amounts are tracked against the expected figure rather than lost.
- Hosted checkout — hand the customer a halfin-hosted link that shows the BTC address, a scannable QR, the exact amount, the network, and a live status. Nothing to render yourself; the page walks the same states as the table above.
- Static deposit addresses — a persistent per-merchant Bitcoin address that does not expire, for deposits and top-ups rather than a single priced sale. Funds arriving on it are credited the same reorg-aware way.
No chargebacks, settled to a balance you control
A confirmed Bitcoin payment is final in a way a card payment is not. There is no issuer to reverse it weeks later and no chargeback window hanging over the sale. Once the transaction has the confirmations the network requires, the value is yours — your exposure on the payment is the wait for confirmations, which halfin manages, not a months-long reversal risk. That is precisely why chargeback-prone and high-risk merchants reach for the Bitcoin rail.
Settled BTC accrues to a balance you control, where it behaves like any other settled value on the platform. Convert it to a stablecoin through balance conversion if you would rather not hold price exposure, pay it out to a destination, or leave it as bitcoin. If you need to return funds to a customer, that flows through refunds as a deliberate, recorded action — there is no automatic reversal, because on-chain there is nothing to automatically reverse.
Create a BTC-payable invoice
Bitcoin acceptance runs on the same spec-first REST API as every other asset. Authenticate with a scoped API key via the X-API-Key header, post the fiat amount and currency, and halfin locks the rate at activation, computes the payable BTC amount, and returns an invoice you can present through hosted checkout or render yourself. Send idempotency_key in the request body so a retried request never creates a duplicate invoice.
The call below is the minimal create. The amount is a string — monetary values are strings end to end, never floats — and the currency is your fiat anchor, not the asset. You do not name BTC here; the customer chooses it at pay time from the networks you support. The exact request and response fields are defined in the docs and the @halfin/sdk-merchant types.
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",
"deferred": true,
"description": "Order #4471",
"idempotency_key": "00000000-0000-4000-8000-000000000001"
}'
# The customer chooses BTC at pay time. halfin locks the rate at
# activation, pins the payable bitcoin amount, and credits the
# deposit reorg-aware once it meets the Bitcoin confirmation
# threshold. See docs.thehalfin.com for the full request/response schema.