Products · M2M settlement

Machine-to-machine settlement

Some payment flows never touch a person. A pricing engine tops up a partner float, a billing job settles a usage period, a reconciliation worker matches deposits to accounts at 3 a.m. halfin exposes its invoicing, payout, conversion, and webhook primitives as a spec-first REST API with idempotency keys and signed events, so one of your services can drive settlement against another with the same guarantees an operator would get in the dashboard — and none of the manual steps.

01

The problem: settlement that has to run without an operator

Most crypto payment tooling assumes a person is watching. Someone reads the dashboard, approves the payout, eyeballs the amount, retries the request when a network call times out. That model breaks the moment settlement has to happen on a schedule, in response to an event, or at a volume no one can babysit. A usage-based billing system closing thousands of accounts at month-end cannot wait for a human to click. A treasury job rebalancing float across desks runs while everyone is asleep.

When you wire payments straight into a backend, two failure modes show up immediately. The first is duplication: a request times out, your worker retries, and now you have paid twice or created two invoices for the same order. The second is blindness: your service fired the call but never learned the real outcome, because the settlement is asynchronous — a deposit confirms minutes later, a payout lands after a block. Both are expensive in exactly the flows where a human is not there to catch them.

halfin's answer is not a separate product — it is the same payment primitives, designed so a machine can call them safely. Idempotency keys make retries free. Signed webhooks turn the asynchronous outcome into an event your worker can trust. Scoped API keys let one automated system act without holding operator-level reach. That combination is what we mean by machine-to-machine settlement.

02

What M2M settlement is in halfin

M2M settlement is programmatic settlement between systems over the halfin API, with no operator in the loop. It is a way of using the platform, composed from primitives you can also drive by hand — not a distinct rail with its own assets or chains. Your service authenticates with a scoped API key, creates the settlement object it needs (an invoice to receive funds, a payout to send them, a conversion to rebalance a balance), and then reacts to the signed webhook that reports the terminal state.

Because it is built on the same objects, M2M flows inherit the same correctness model the rest of the platform uses: fiat-anchored amounts with a rate locked at activation, expiry on invoices, underpaid and overpaid handling, reorg-aware crediting, and per-chain confirmation thresholds. A machine driving the flow gets exactly the settlement semantics an operator would — it just gets them through code.

The table below maps the common automated intents to the halfin primitive that carries them. Each links to its own product page where the mechanics are covered in full.

Automated intenthalfin primitiveHow the machine drives it
Receive funds for an order or usage periodInvoicingPOST an invoice with a fiat-anchored amount; webhook confirms paid
Pay one counterparty programmaticallySingle payoutsPOST an approved payout to a destination address; webhook confirms completion
Fan out many payouts in one runMass / batch payoutsPOST an idempotent batch; per-item state reported back
Rebalance a balance between assetsBalance conversionTrigger a conversion; treasury logic stays automatic
Assign a persistent receive point to an accountStatic deposit addressesMap a per-account address once; deposits credit on confirmation
03

Idempotency: retries that never double-settle

The defining requirement of unattended settlement is that retrying is safe. Networks drop responses, workers crash mid-call, queues redeliver — and in a money flow, an accidental second request is not a glitch, it is a second payment. halfin handles this with idempotency keys on the operations that create or move value.

Your service generates a stable key for each logical settlement — derived from the order ID, the billing period, the batch run, whatever uniquely names the intent. You send that key with the request. The first call does the work; any repeat of the same key returns the original result instead of acting again. A worker can fail and replay its whole queue without paying anyone twice, and you do not have to build a deduplication layer of your own around the API.

Batch payouts extend the same idea to a whole set: re-submitting an identical batch never re-pays the recipients who already settled. For a machine that must guarantee at-least-once delivery of its own jobs, this turns the dangerous case — an over-eager retry — into a no-op.

04

Webhooks: how a machine learns the real outcome

Settlement is asynchronous. A POST that creates an invoice returns immediately, but the money arrives when a customer pays and the deposit confirms — possibly minutes later, across several blocks. A payout request is accepted in milliseconds; the funds land after the chain confirms. Polling for these transitions is wasteful and slow, and it is exactly the kind of busy-work that ages badly at scale. halfin reports terminal and intermediate states by pushing a signed webhook to your endpoint.

Every webhook carries an HMAC signature over a typed event envelope, sent in the x-halfin-signature header. The contract is firm: recompute the HMAC over the exact raw request bytes — before any JSON parsing or middleware reserializes the body — compare it to the header in constant time, and only then act. A machine consuming events must confirm the payload is genuinely from halfin and untampered before it credits an account, releases a service, or marks an invoice settled. Skipping that check turns your settlement endpoint into something an attacker can forge events against.

Treat webhooks as the trigger and the API as the source of truth. When an event tells your worker that an invoice reached its paid state or a payout completed, the worker advances its own state machine; if it ever needs to be certain, it reads the object back from the API. Deliveries are retried, so your endpoint should be idempotent on the receiving side too — handle the same event arriving more than once without re-running the side effect.

import { createHmac, timingSafeEqual } from "node:crypto";

// Verify the signature BEFORE acting on any halfin webhook.
// Compute the HMAC over the RAW request bytes, before any JSON
// parsing reserializes the body and breaks an otherwise-valid match.
export function verifyHalfinWebhook(
  rawBody: Buffer,
  signatureHeader: string, // x-halfin-signature
  signingSecret: string,
): boolean {
  const expected = createHmac("sha256", signingSecret)
    .update(rawBody)
    .digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signatureHeader);
  return a.length === b.length && timingSafeEqual(a, b);
}

// In your settlement worker:
//   1. verify the signature (above) — reject with 4xx if it fails
//   2. parse the typed event envelope
//   3. advance your own state machine idempotently
//   4. if certainty is required, read the object back from the API
05

Scoped keys: least privilege for an automated caller

A service that only ever creates invoices should not be able to send payouts. A reconciliation worker that only reads settlement state should not be able to move funds at all. halfin issues API keys with scoped permissions, so each automated caller carries exactly the reach its job needs and nothing more.

This matters more for machines than for people. An operator's mistake is bounded by how fast they can click; an automated caller runs in a loop. If a key leaks or a service is compromised, the blast radius is the key's scope. Giving your billing worker a create-invoice-and-read key, your payout job a payouts key, and your accounting export a read-only key keeps a single failure from becoming a treasury incident.

Pair scoped keys with idempotent requests and signature-verified webhooks and you have the full unattended-settlement contract: a caller that can only do its one job, retries that cannot double-settle, and outcomes that cannot be forged.

  • Read-only key for the reconciliation and accounting jobs that consume state.
  • Create-invoice key for the billing or order service that collects funds.
  • Payouts-scoped key for the worker that disburses, kept separate from collection.
  • Rotate and revoke per service — a leaked key is contained to its scope.
06

A worked flow: usage billing that closes itself

Consider a platform that bills partners for metered usage at the end of each period. At close, a job iterates accounts and, for each one, generates an idempotency key from the account ID and the period, then creates a fiat-anchored invoice for the usage total. The amount is quoted in the partner's currency; the rate locks at activation, so neither side carries the FX swing while the invoice is open.

The partner's own system pays the invoice on a supported chain. halfin watches the deposit, applies the chain's confirmation threshold and reorg-aware crediting, and pushes a signed webhook when the invoice reaches its paid state. The billing platform's worker verifies the signature, marks the period settled, and unblocks the next cycle — all without a person reading a dashboard.

The reverse direction is symmetric. A revenue-share or float-replenishment job builds a batch payout, signs each request with a per-run idempotency key, and submits it; halfin reports each item's outcome by webhook, and a re-submitted batch never double-pays. Between the two, conversion can keep the settlement balance in the right asset automatically, so the machine never has to ask a treasurer which token to hold.

07

Boundaries: what M2M settlement does not do

M2M settlement is a payment layer, not a system of record for your business logic. halfin executes the settlement, guarantees idempotency, and reports outcomes; your service still owns the decision to settle, the account model, and the ledger those payments reconcile against. The platform does not invent counterparties, approve spend against your policy, or replace the workflow that decides an invoice is owed.

It is also not a fiat on-ramp. halfin does not sell crypto to your counterparties or convert bank money into digital assets — it settles in the supported assets and chains, between systems that already transact in them. Custody assurances stay where the platform actually provides them: scoped permissions, signing, and an audit trail, not a guarantee beyond those.

Where a human decision genuinely belongs in the loop — an unusual payout, a manual treasury move — keep it there using the dashboard and operator-driven flows. M2M settlement is for the paths that are well-defined enough to run on their own, and it is deliberately scoped to those.