Use case

Usage-based pricing in crypto

Usage-based pricing flips the order of subscription billing: you do not know the amount until the period closes. A customer runs API calls, processes gigabytes, or sends messages all month, and only when the meter stops do you know what they owe. In crypto that maps onto one clean step — tally the metered total in your own system, then issue a single fiat-anchored invoice for that figure. halfin locks the rate at activation, the customer pays from their wallet, and a signed webhook closes the period. No card sits on file waiting to be charged an amount you could not predict in advance.

01

Metered pricing is post-paid, so the amount comes last

A flat subscription knows the price up front: the same fee every cycle, billed on a fixed date. Usage-based pricing does not. The customer consumes a metered resource — API requests, compute minutes, storage, seats that scaled mid-month, messages sent — and the amount owed is whatever that consumption adds up to when the period closes. You are billing after the fact, against a number your own system produces.

On cards, that post-paid shape is hidden inside a stored credential: the processor charges whatever you submit at period end against the card on file, and the customer sees the charge after it lands. Crypto has no credential to charge, so the post-paid step becomes explicit. When the meter stops, you compute the total and issue an invoice for it; the customer chooses to pay it from their wallet. The act of paying is visible, and the amount is whatever the meter said — re-stated in crypto at the rate that holds when the invoice goes live.

This is the right place to draw the line between your system and halfin. Metering — counting the units, applying your rate card, handling tiers, overage, and credits — stays entirely inside your product, because it is your pricing logic and your source of truth. halfin's job starts at the figure: take the fiat total you computed, anchor an invoice to it, collect the payment on-chain, and tell you when it settled.

  • The amount owed is unknown until the period closes — metered billing is post-paid by nature.
  • Counting units, tiers, overage, and credits is your pricing logic, not halfin's.
  • halfin starts at the computed fiat total: anchor, collect, confirm, report.
  • There is no stored credential — the customer pays a stated amount from their wallet.
02

Tally usage, then issue one invoice for the period total

The integration is a single hand-off at the end of each billing period. Your usage-rollup job closes the meter for an account, applies your rate card to get a fiat total — say USD 312.40 for the month's API calls — and creates one fiat-anchored invoice for exactly that amount. halfin quotes the equivalent in the assets you accept and locks that rate at activation, so the customer pays a fixed figure inside a defined window rather than chasing a number that drifts while they read it.

The customer settles through hosted checkout or a checkout you render yourself against the same API. halfin watches the chain, applies that chain's confirmation threshold, and credits the deposit reorg-aware. When the invoice resolves, your server receives an HMAC-signed webhook — verify the signature, then mark the billing period closed for that account and start the next meter. That webhook, not the browser redirect and not a polling loop, is the authoritative signal that the period was paid.

There is no separate metered-billing endpoint to learn. It is the same invoicing primitive a flat plan uses, called once per period with a different amount each time — the amount your meter produced instead of a fixed fee. The fiat anchor means your pricing, your rate card, and your revenue reporting all stay in dollars or euros, while the customer settles in USDT, USDC, or a native asset.

Period stepYour system doeshalfin does
Period closesClose the meter; apply the rate card to get a fiat total
Issue the billCreate one fiat-anchored invoice for the metered totalQuote the asset amount, lock the rate at activation, stamp an expiry
Customer paysPresent hosted or self-hosted checkout; wait for the webhookWatch the chain, apply the confirmation threshold, credit reorg-aware
Period settlesVerify the signature, close the period, start the next meterSend the HMAC-signed invoice.paid event
Customer does not payTreat the expiry as an unpaid period; apply your collections policySend the HMAC-signed invoice.expired event after the window lapses
03

Creating the invoice for a metered period

The create call is the same one a flat subscription makes, with one difference: the amount is the figure your meter produced this period, not a constant. You compute it, format it as a string — monetary values are strings end to end, never floats, so a fraction of a cent is never lost to binary rounding — and post it as the fiat amount with your fiat currency as the anchor.

Scope the idempotency key to the period so a retried rollup job never bills twice. A usage-rollup worker is exactly the kind of job that runs again after a timeout or a crash, and without a key that means two invoices for one period and a customer billed twice for the same usage. An account ID plus the billing period is a natural key shape; a repeat call with the same key returns the existing invoice instead of issuing a second one.

The request below bills one account for a closed metered period. The same call is what a nightly rollup, an end-of-month batch, or a threshold-triggered job would make — the invoicing primitive, called once per period, carrying the amount the meter produced.

# Called once per metered period by your usage-rollup job.
# amount_fiat is the figure your meter produced this period, as a string.
# idempotency_key is scoped to the period (account + period), so a retried
# rollup returns the existing invoice instead of billing the usage twice.
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": "312.40",
    "fiat_currency": "USD",
    "deferred": true,
    "description": "Metered API usage — acct_42 — 2026-06",
    "idempotency_key": "usage-acct_42-2026-06"
  }'

# halfin locks the rate at activation, pins the payable asset amount,
# and returns an invoice you present via hosted or self-hosted checkout.
# Close the period on the signed invoice.paid webhook — verify the HMAC
# signature before acting. Full request and response schemas: docs.thehalfin.com.
04

Underpaid and overpaid metered invoices land in defined states

A metered total is rarely a round number, and a customer paying USD 312.40 worth of USDT from an exchange that skims a withdrawal fee, or fat-fingering the amount, will sometimes send slightly too little or too much. A naive integration treats anything that is not an exact match as a failure and strands the money. halfin records the gap against the invoice instead.

An underpayment surfaces the shortfall on the invoice, so you can request a top-up or settle the period partially under your own policy rather than pretending the funds never arrived. An overpayment records the excess against the invoice so it is visible and accountable — you decide whether to credit it toward next period's usage or refund it. Each outcome is a separate, signed event your billing logic can act on: invoice.underpaid and invoice.overpaid carry the same HMAC signature you verify before acting, alongside invoice.paid for a clean settlement and invoice.expired for a window that lapsed unpaid.

Because crediting respects per-chain confirmation thresholds and is reorg-aware, the settled amount you close the period against is an amount that actually held on-chain. You are not closing a metered period on a payment that a chain reorganization later unwinds.

  • invoice.paid — the metered total settled; close the period and start the next meter.
  • invoice.underpaid — the customer sent too little; request a top-up or settle per policy.
  • invoice.overpaid — the customer sent too much; credit forward or refund the excess.
  • invoice.expired — the window lapsed unpaid; treat it as an open period for collections.
  • Verify the HMAC signature on every event before taking any business action.
05

Prepaid credit and hybrid plans are the same primitive, used differently

Not every consumption product bills strictly after the fact. Some sell prepaid credit — the customer tops up a balance, and usage draws it down — and some run a hybrid: a flat platform fee plus metered overage. Both fit the same invoicing primitive without a new mechanism.

For prepaid credit, the invoice is not tied to a closed meter at all; it is a top-up the customer initiates for a fiat amount they choose, and your system increments their internal credit balance on the invoice.paid webhook. The metering then runs entirely inside your product against that balance, with no halfin invoice per unit of usage — halfin sees only the top-ups, and your ledger sees the draw-down. For a hybrid plan, the period-end invoice carries the base fee plus the computed overage as a single fiat total; the customer sees one amount, and your description line records the split.

The thread through all three shapes — post-paid metered, prepaid credit, and hybrid — is that halfin never models your meter. It models the bill. Your product decides what a customer owes and when; halfin anchors that figure to fiat, collects it on-chain, and reports settlement. Keeping the meter on your side is what lets one primitive cover pricing models that look very different to the customer.

06

Where this leads next

Usage-based pricing is the invoicing primitive called once per period with a variable amount, so invoicing itself is the place to start — it owns the fiat anchor, the activation-time rate lock, the expiry window, and the underpaid and overpaid states this whole flow depends on. Read that first; everything here is that primitive driven by a meter.

The integration is an API-first job: a usage-rollup worker that computes the total, a programmatic invoice create with a period-scoped idempotency key, and a signed-webhook handler that closes the period. Wire the webhook before anything that closes a billing period, since it is the only authoritative signal the period was paid. The parent SaaS use case covers the surrounding surface — flat recurring billing, checkout choice, and paying a developer ecosystem from the same balance.