Anchor the amount in the currency you actually account in
A token-only invoice — "send 0.00071 BTC" — pushes a problem back onto you. The number on the bill is meaningful to the customer's wallet and to nobody in your accounting. You priced the thing in USD, your contract is in USD, your revenue recognition is in USD, and now you have to back-convert every settled payment to know what it was worth.
A fiat-anchored invoice inverts that. You declare the amount in fiat and name the currency; halfin derives the payable token amount from the live rate and carries both figures on the same object. The customer sees a concrete token amount to send, and you keep the fiat figure as the source of truth for reconciliation. The conversion happened once, at a known moment, and it is recorded against the invoice — not reconstructed later from a rate you have to go find.
The two fields that drive this are deliberately plain. amount_fiat is the value you are billing, sent as a string so it never picks up a floating-point rounding error in transit. fiat_currency names the anchor — USD, EUR, and the other fiat currencies halfin supports for denomination. That is the whole anchoring contract: one amount, one currency, and a payable token figure that halfin computes for you.
deferred: choose the asset at create-time or let the payer pick
Fiat anchoring works in two modes, and the deferred flag is what selects between them. The difference is about when the payable asset is decided, not about whether the fiat figure is honored — the fiat anchor holds either way.
With deferred set true, you create the invoice with only the fiat amount and currency and leave the asset open. The payer is presented the supported networks and assets and settles in whichever one they hold — USDT on Tron, USDC on Base, BTC, ETH, SOL, XRP, or a native chain asset. This is the right mode for a hosted-checkout flow where you do not know in advance what the customer will reach for.
Without deferred, you pin the settlement asset and network yourself at creation — useful when you already know the customer pays in, say, TRC-20 USDT, or when you are rendering a single-asset payment page. In both modes the rate against your fiat anchor is locked at activation and the amount you reconcile is the fiat amount you billed.
- deferred true — fiat amount only at create-time; the payer selects the asset and network at checkout.
- deferred false — you pin the settlement asset/network up front for a single-asset flow.
- Same anchor either way — the locked rate and the reconciled fiat figure do not depend on which mode you used.
The rate locks at activation, not at create-time
Crypto prices move on a timescale that matters for a checkout. If the quote were fixed when you drafted the invoice and the customer paid twenty minutes later, the token amount could drift far enough to leave you short or leave them overpaying. halfin closes that window by locking the conversion rate when the invoice activates — the moment it goes live and is presented for payment.
From activation, the payable token amount is frozen for the life of that invoice and an expiry window is stamped. Pay inside the window and the asset amount the customer was shown settles to exactly your billed fiat figure. Let the window lapse and the invoice is marked expired rather than silently re-pricing against a newer rate — you decide whether to re-issue at the current rate. Nobody is ever exposed to a rate they did not agree to: not you, not the customer.
Reconcile against the fiat figure, every asset, every chain
Because the fiat amount is the anchor, reconciliation is mechanical regardless of how the customer paid. Each settled invoice maps back to the amount you billed, with the asset and network it arrived on recorded alongside. The table below shows the same $49.00 anchor settling across different assets — the fiat figure is constant; only the payable token amount and the rail change.
| fiat anchor | Payer settles in | Network | Reconciles to |
|---|---|---|---|
| 49.00 USD | USDT | Tron (TRC-20) | 49.00 USD |
| 49.00 USD | USDC | Base | 49.00 USD |
| 49.00 USD | BTC | Bitcoin | 49.00 USD |
| 49.00 USD | ETH | Ethereum | 49.00 USD |
| 49.00 USD | SOL | Solana | 49.00 USD |
Create a fiat-anchored invoice with one call
Anchoring is spec-first REST. You authenticate with a scoped API key and post the fiat amount and currency; halfin computes the payable asset amount at activation and returns an invoice you present through hosted checkout or render yourself. The only request headers are X-API-Key and Content-Type. Idempotency is a body field — idempotency_key in the JSON — so a retried request never creates a duplicate invoice; there is no Idempotency-Key header.
Here is a minimal deferred create call. amount_fiat is a string because monetary values are strings end to end, never floats, and fiat_currency is the anchor. With deferred true the asset is left for the payer to choose. The full response schema lives 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": "49.00",
"fiat_currency": "USD",
"deferred": true,
"description": "Pro plan — March",
"idempotency_key": "00000000-0000-4000-8000-000000000001"
}'
# deferred=true leaves the asset open: the payer picks any supported
# asset at checkout. halfin locks the rate against USD at activation
# and pins the payable token amount. Track state via signed webhooks —
# verify the HMAC signature before acting. See docs.thehalfin.com.Where fiat anchoring sits in the flow
A fiat-anchored invoice is what a hosted checkout renders for the customer, and the same object is available if you build the payment UI yourself. When the invoice changes state — confirming, paid, overpaid, underpaid, expired — a signed webhook tells your backend; verify the HMAC signature, then fulfill against the original fiat figure. Crediting is reorg-aware and waits for the per-chain confirmation threshold, so the amount you book as settled is one that actually held on-chain.
Fiat anchoring pairs naturally with multi-currency invoices, where a single anchored invoice presents the full supported asset surface to the payer. On the presentation side, hosted-checkout customization controls how that payable amount and asset choice are shown, and QR-code payments turn the derived token amount and address into a scan-to-pay flow. The anchor is the constant; the rest is how you present and settle it.