Compliance is a process you run, not a status halfin holds
Start with the division of responsibility, because it is easy to assume a payment provider absorbs more of it than it does. halfin is digital-asset payment infrastructure: it collects a crypto deposit, executes an approved payout, and reports both through signed webhooks. It is not a license, it does not onboard your traders, and it does not decide whether a particular customer or withdrawal is allowed. KYB onboarding and AML awareness are an ongoing process your firm runs — never a certification a payment rail confers on you.
That plays out operationally as a clean boundary. The decision to accept a deposit, fund a challenge account, or release a withdrawal stays inside the broker's stack — your CRM, your risk desk, your KYC vendor, your sanctions tooling. halfin executes the instruction you already approved and keeps durable records of every movement so you can evidence it later. You own the eligibility decision and the regulatory status; halfin owns moving the money and recording that it moved. A broker that treats its payment provider as its compliance function has a gap exactly where an auditor will look.
- halfin is payment infrastructure, not a license — it never carries your regulatory status or makes your eligibility decisions.
- KYB and AML are continuous process inside your stack, not a certification a rail confers.
- You own the decision to accept a deposit or release a withdrawal; halfin executes the already-approved instruction.
- Every deposit and payout leaves a durable, signed record you can produce as evidence later.
Trader identity stays in your stack — the deposit attaches to it
Your AML program starts at onboarding, and onboarding is yours: collect identity, verify it, risk-rate the trader, and decide they may fund an account before any crypto enters the picture. The rail does not replace that step or even touch it. What it does is give you a payment record you can tie back to the trader you already identified, so the deposit is never an anonymous inflow you reconcile after the fact.
Concretely, you set your own trader or account identifier on the invoice when you create it, and that identifier rides through to the invoice.paid webhook and the dashboard record. A given deposit then maps one-to-one to a KYC'd trader, on a known chain, for a known fiat-anchored amount. When a reviewer asks who funded this account and how, the answer is a record, not a guess.
The same discipline applies in reverse on withdrawals. The wallet you pay to should be one your process associates with the identified trader, not an address that appeared for the first time at withdrawal time. halfin will send to whatever destination you submit — it does not adjudicate ownership — so the control that the payout address belongs to the right person is yours to enforce before you create the payout.
- Onboarding, identity verification, and risk-rating happen in your stack before any deposit — the rail doesn't change that.
- Set your trader/account id on the invoice; it flows to invoice.paid and the dashboard, linking funds to a verified customer.
- Each deposit reconciles to a known trader, known chain, and known fiat amount — no anonymous inflow to chase later.
- Associating the payout wallet with the identified trader is your control; halfin sends to the destination you submit.
Sanctions and wallet-risk screening sit on both legs
Screening in a crypto context has two faces. The first is the name-and-entity sanctions screening you already run against your customer base — it does not go away because the trader pays in USDT, and it stays your obligation against the people you onboard and the counterparties you pay. The second is specific to on-chain money: screening the wallet address itself for exposure to sanctioned, stolen, or otherwise tainted funds, using blockchain-analytics tooling your firm selects and operates.
Apply both before money moves, on each leg: on the deposit leg to avoid crediting a trading account from a flagged source, on the withdrawal leg to avoid sending funds to a flagged destination. Because halfin payouts enter a pending-approval state and are released from the dashboard by an operator, your process has a natural gate — run wallet and counterparty screening, then release the payout. The rail will not execute until a human has approved, which is exactly where a screening step belongs.
Reorg-aware crediting helps here too, as a settlement property rather than a screening one. halfin waits for the per-chain confirmation threshold and reflects a chain reorganization that unwinds a transaction rather than ignoring it, so the deposit you screen and credit is one that actually held on-chain — not a payment that later evaporates.
| Leg | What to screen | When | Who owns it |
|---|---|---|---|
| Deposit | Sending wallet's on-chain risk exposure; trader already KYC'd at onboarding | Before crediting the trading account on invoice.paid | Broker (analytics tooling + AML process) |
| Withdrawal | Destination wallet risk; payee name against sanctions lists | While the payout is pending-approval, before release | Broker (the dashboard release is the gate) |
| IB / affiliate payout | Payee identity and wallet, same as a withdrawal | Before releasing the commission run | Broker (keep payee list under your controls) |
An evidence trail you can actually produce
Whatever your jurisdiction's record-keeping expectations are, they are easier to meet when the payment system hands you a complete, queryable history rather than a folder of screenshots. Every invoice and payout halfin processes is a durable record — amount, asset, network, status, timestamps, and your own attached identifier — visible in the dashboard and through the API. That is the raw material an AML review or an external audit runs on, and it exists without you building a separate ledger to capture it.
The webhook layer is what lets you bind that history into your own system of record at the moment events happen rather than reconstructing it later. The canonical events are deliberately small and well-defined: invoice.confirming, invoice.paid, invoice.underpaid, invoice.overpaid, invoice.expired, and payout.completed. Each is HMAC-signed, and the rule that protects the integrity of your trail is simple — verify the signature before you act on or record an event. An unverified webhook is not evidence of anything; a verified one is a payment fact you can attach to a trader file.
Reconciliation is where the trail earns its keep. Because each event carries your identifier and the deposit or withdrawal it describes, your finance and compliance systems tie every movement of money back to a specific trader or IB without manual matching. When a reviewer asks to walk a trader's deposits and withdrawals end to end, the answer is a join across records you already hold, keyed to events you already verified. The sketch below shows the order that protects that trail — compute the HMAC over the raw body, compare it in constant time to the signature header, and only then record the event; the exact header name and signing scheme are in the docs.
// Webhook receiver — verify the HMAC signature BEFORE recording the
// event into your compliance/reconciliation store. An unverified
// payload is not evidence; never act on it. See docs.thehalfin.com for
// the exact header name and signing scheme.
import { createHmac, timingSafeEqual } from 'node:crypto';
function handleWebhook(rawBody, signatureHeader, signingSecret) {
const expected = createHmac('sha256', signingSecret)
.update(rawBody)
.digest('hex');
const ok = timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader),
);
if (!ok) return reject('invalid signature');
const event = JSON.parse(rawBody);
// event.type is one of: invoice.confirming | invoice.paid |
// invoice.underpaid | invoice.overpaid | invoice.expired |
// payout.completed. Attach it to the trader/IB id you set on the
// invoice or payout, then record it for reconciliation and audit.
recordForAudit(event);
}Where the boundary holds, and what to confirm with counsel
Pulling it together: your firm runs the compliance program, and halfin gives that program a payment surface that is identity-linked, screenable on both legs, and fully recorded. Onboarding, KYC, suitability, risk-rating, sanctions screening, and the decision to allow any given deposit or withdrawal stay with you. halfin collects the deposit reorg-aware, holds payouts for your approval, executes the released instruction, and reports both directions through signed webhooks you reconcile against trader IDs.
A few common places to slip. The travel rule and similar are concepts and process to understand and, where applicable, implement — not a certification halfin carries on your behalf. The redirect a customer's browser makes back from hosted checkout is not proof of payment — only the verified invoice.paid webhook is. And the dashboard release on a payout is a control point, not a formality: it is where your screening and approval bite before funds leave the balance.
The honest caveat: compliance obligations for FX, CFD, and prop-firm activity vary by jurisdiction and by the markets you serve, and they change. Nothing here is legal or financial advice, and none of it describes a regulatory status that halfin holds or grants. Use it to understand how the payment primitives fit a program you design, then confirm the specifics — what you must collect, screen, retain, and report — with your own compliance counsel. The adjacent FX brokerage pages cover the funding and payout mechanics this view sits on top of.
- You own onboarding, KYC, screening, and the deposit/withdrawal decision; halfin owns collection, approval-gated execution, and signed records.
- Travel rule and similar are process to understand and apply where applicable — never a status a rail confers.
- Trust the verified invoice.paid webhook, not the checkout redirect; the payout dashboard release is a real control point.
- Obligations vary by jurisdiction and change — this is not legal advice; confirm specifics with your own counsel.