A crypto payment gateway is a system that issues a payment request to a customer, watches the blockchain for the matching transaction, decides when that transaction is final and clean, credits the merchant in an internal ledger, and notifies the merchant's backend. Everything else, from dashboards to fiat conversion, sits on top of that loop.
Building one comes down to nine decisions, in this order:
| Stage | Key question | Output |
| Model | Do you hold merchant funds? | Custody model, licensing map |
| Approach | Build, white-label, or integrate? | Build-vs-integrate decision tied to volume |
| Chains | Which assets do your merchants' customers actually pay with? | Chain list, node or RPC plan |
| Wallets | Where does an unscreened deposit land? | Buffer, hot, and cold wallet design |
| Engine | When is a payment final? | Invoice state machine, confirmation rules |
| Compliance | What happens to a high-risk deposit? | KYT flow, quarantine process |
| Integration | How does a merchant trust your callback? | API, signed webhooks, docs |
| Launch | Does it work with real money? | Mainnet test report, audit, pilot |
The payment path works like this. The checkout calls the merchant API, which creates an invoice with an amount, a locked rate, and an expiry, then assigns a deposit address. A listener, backed by your own node or an RPC provider, detects the incoming transaction. The confirmation tracker waits until the network-specific threshold is met. KYT screening scores the transaction and either releases it or sends it to quarantine. Clean funds move from the deposit or buffer wallet to the hot wallet, the ledger records the credit, and the webhook dispatcher notifies the merchant.
Finality time differs by network, and merchants need to see it in the checkout. In one exchange deployment, we observed time-to-credit of roughly 18 minutes on Ethereum, about 1 hour 40 minutes on Bitcoin, and 2 to 3 minutes on TRON under that platform's confirmation settings. Treat these as an illustration of the spread, not as targets.
Two infrastructure habits save weeks. First, start node synchronization in week one: a Bitcoin full node takes five to ten days to sync in our deployments, while TRON and BNB Smart Chain nodes take one to three days. Second, process deposits and withdrawals as separate job queues rather than a sequential cron. On one exchange we moved away from cron-based processing after it skipped execution windows under load. If you are designing the rest of the platform too, the same service boundaries appear in how trading platforms are built at scale.
| Option | What you own | Custody risk | Fits when | Main limitation |
| Hosted processor integration | Checkout UX, your business logic | Held by the provider | Low or unproven volume, standard assets | Provider's fees, asset list, and freeze decisions |
| White-label gateway | Branded deployment, configuration | Yours, on proven code | You need your own gateway fast with standard flows | Deep changes to settlement or compliance logic |
| Custom build | Code, wallets, nodes, compliance logic | Yours, fully | High volume, unusual settlement, strict custody requirements | Highest upfront cost and ongoing operations |
On a B2B payment platform we worked on, the team compared three paths for its crypto flow: a manual MVP through a single buffer wallet, where the customer submits a transaction hash and an admin verifies it in a block explorer; integration with a ready-made gateway; and a custom stack with its own node, address generation, and monitoring. The custom stack was estimated at 20 to 100 times the cost of integration or the manual flow. For 10 to 20 transactions a week, the manual flow was economically justified. Above that, integration made sense. Own infrastructure only became worth it at much higher turnover, or if a third-party provider's custody or freeze risk was unacceptable.
If a ready-made base is closer to what you need, compare it against a white-label crypto payment gateway before committing to a full custom build. When your volume or settlement rules rule out both off-the-shelf paths, scope the project as crypto payment gateway development with custody and compliance defined up front.
We faced this choice on a B2B payment platform that accepts crypto deposits from companies. It is not a merchant checkout, but the deposit problem is the same.
The challenge: pre-screening a customer's wallet did not guarantee the payment would come from that wallet. If funds from an unknown address went straight to the hot wallet, they would already be mixed with clean assets by the time anyone noticed.
The solution we designed has four parts. The customer first adds a wallet to their profile, and it passes KYT screening through Crystal before it is whitelisted. Only then does the customer see a deposit address. Incoming funds land on a buffer wallet, not the hot wallet. The system compares the actual sender address with the whitelisted one and freezes the deposit for manual review on a mismatch. Only screened funds move on to the hot wallet in a second transaction.
| Buffer wallet | Direct hot wallet | |
| Unscreened funds in treasury | No, isolated until checks pass | Yes, mixed on arrival |
| On-chain transactions per deposit | Two | One |
| Network fees | Double, plus a decision on who pays the internal move | Single |
| Engineering scope | Sweep logic, fee calculation, fee accounting | Sender verification only |
| AML exposure | Contained in a quarantine layer | Carried by the entire treasury wallet |
The trade-off is real. The second transaction adds network fees and code, and on that project the question of who pays for the buffer-to-hot move stayed open at the design stage. A single shared buffer wallet per currency also has a limit: it still mixes deposits with different risk profiles in one pool. Full isolation requires an address per customer or per invoice, which brings in address generation and sweep infrastructure. On a separate exchange deployment, we used exactly that pattern: a unique deposit address per user, with funds swept into a corporate hot wallet across Ethereum, Bitcoin, TRON, and Solana. Key storage and signing for those addresses follow the same principles as building a crypto wallet app.
Screening thresholds need the same care. On an exchange deployment integrated with Crystal, transactions scoring 0 to 0.5 were auto-approved and those scoring 0.5 to 1 went to manual review, with the check running on the deposit wallet before crediting. Deposits that fail screening should not disappear into a support queue. On another exchange, failed deposits moved to an isolated quarantine space where the user submits a return address and documents, and an admin approves or rejects the return. The same segmentation logic appears in our guide to crypto exchange security.
| In the MVP | Later versions |
| One or two stablecoins on one or two networks | Long-tail assets and additional chains |
| Invoices with expiry and a locked rate | Recurring billing and subscriptions |
| Explicit states for underpaid, overpaid, expired | Automated partial refunds |
| KYT screening before crediting, manual review queue | Automated risk routing across multiple providers |
| Merchant API, signed webhooks, sandbox | E-commerce plugins and SDKs |
| Double-entry ledger and daily reconciliation | Advanced analytics and custom reports |
| Hot wallet balance alerts and an admin audit log | Automated crypto-to-fiat settlement |
Keep the admin side narrow too. On a B2B payment platform, the first release ran balance conversion through an admin on request instead of self-service. Automated conversion can wait until you know which crypto liquidity providers fit your settlement currencies.
A workable invoice lifecycle: created → awaiting_payment → detected → confirming → screening → paid, underpaid, overpaid, expired, or quarantined → settled, with late_payment and refund_requested as side branches.
| Case | Risk | Handling |
| Underpayment | Merchant ships against partial payment | Mark underpaid, show the remaining amount until expiry, then refund or let the merchant accept |
| Overpayment | Excess funds with no owner in the ledger | Credit the invoice amount, record the surplus as a refundable balance |
| Payment after invoice expiry | Rate moved, order already cancelled | Late_payment state, recalculate at the current rate or refund |
| Second payment to the same address | Double credit or lost funds | Match by transaction hash, never by address alone; treat the second transfer as a new unmatched deposit |
| Wrong network or token | Funds stuck on an unsupported chain | Show network and token contract in the checkout; define a manual recovery process and its fee in the terms |
| Chain reorganization or dropped transaction | Crediting a payment that disappears | Credit only after the network threshold; keep the listener able to reverse unconfirmed detections |
| Amount below the minimum | Sweep costs more than the deposit | Enforce and display a minimum; on one exchange the minimum credited deposit was 3 USDT |
| Sender fails KYT or is not whitelisted | Tainted funds in treasury | Freeze and route to quarantine before crediting |
| KYT provider unavailable | Unscreened funds marked clean | Fail closed: hold the deposit until screening completes |
| Not enough gas or network resources for the sweep | Deposit stuck between wallets | Automated balance polling and resumption, alerts on hot wallet thresholds |
| Webhook delivery failure | Merchant never fulfills a paid order | Retries with backoff, idempotency keys, a dead-letter queue, and a status endpoint merchants can poll |
For keys and wallets, keep only operating liquidity in hot wallets, move the rest to cold storage, and alert when hot balances fall below a threshold. On one exchange, the hot wallet alert fired when a balance dropped below the equivalent of 800 USDT per asset, repeated up to five times at 10-minute intervals, and stopped as soon as the balance recovered. Each alert carried the coin, network, native balance, USDT equivalent, threshold, and the rate used for conversion.
For the merchant API, authenticate every request with an API key and sign every webhook. HMAC with SHA-256, as defined in RFC 2104, lets the merchant verify that a callback came from you and was not altered. Include a timestamp in the signed content so the merchant can reject replayed requests, and an event ID so repeated deliveries are processed once.
Example webhook request:
POST /webhooks/crypto-payments HTTP/1.1
Content-Type: application/json
X-Gateway-Event-Id: evt_01J9ZK4Q2M8R
X-Gateway-Timestamp: 1789113600
X-Gateway-Signature: sha256=4f1c9a0d3b7e...
{
"event": "invoice.paid",
"invoice_id": "inv_7Q3K9P",
"merchant_order_id": "A-10442",
"status": "paid",
"asset": "USDT",
"network": "TRON",
"amount_requested": "150.00",
"amount_received": "150.00",
"tx_hash": "b3e1f0...9ac2",
"confirmations": 20,
"kyt_status": "clear",
"paid_at": "2026-09-17T10:40:00Z"
}
Merchant-side verification in Node.js:
const crypto = require("crypto");
function verifyWebhook(rawBody, headers, secret) {
const timestamp = headers["x-gateway-timestamp"];
const received = (headers["x-gateway-signature"] || "").replace("sha256=", "");
// Reject requests older than 5 minutes to block replays
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(received, "hex");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// Store X-Gateway-Event-Id and skip events that were already processed
Sign the raw request body, not re-serialized JSON, because key order and whitespace changes break the signature.
For operational controls, log every admin action that moves money with the initiator, time, requested amount, executed amount, balance after, and final status. On one exchange, a post-migration check found that hot wallet withdrawals were not producing a full audit record even though viewing a deposit address was logged. After any infrastructure migration, re-test observability, not just the business function.
| Model | United States | European Union |
| Custodial gateway (you receive and pass funds to merchants) | FinCEN treats CVC payment processors as money transmitters; state money transmitter licensing may also apply depending on the states served | Crypto-asset services generally require MiCA CASP authorization; Transfer of Funds Regulation (Travel Rule) applies to transfers |
| Non-custodial software (funds go directly to merchant-controlled wallets) | Obligations depend on whether you accept and transmit value; requires legal analysis of the specific flow | Depends on whether you provide a crypto-asset service under MiCA; requires legal analysis |
| Crypto-to-fiat settlement | Money transmission analysis plus banking partner requirements | CASP authorization for exchange services, plus payment services rules for the fiat leg |
| Stablecoin-focused platform | GENIUS Act affects which payment stablecoins may be offered once rules take effect | MiCA rules for e-money tokens affect which stablecoins are offered |
In the US, FinCEN guidance FIN-2019-G001 states that CVC payment processors fall within the definition of a money transmitter and do not qualify for the payment processor exemption, because they do not operate through clearance and settlement systems limited to BSA-regulated institutions. The GENIUS Act, signed on July 18, 2025, takes effect on the earlier of January 18, 2027 or 120 days after final implementing rules. Treasury's August 2026 proposed rule on stablecoin issuance, offer, and sale was still open for comment through October 19, 2026, so the asset list you offer US merchants carries regulatory risk that is still being defined.
In the EU, the transitional period for crypto-asset service providers under MiCA ended on July 1, 2026. MiCA itself does not set AML or Travel Rule duties; those come from AML directives and the Transfer of Funds Regulation, which has required originator and beneficiary data on crypto-asset transfers since December 30, 2024.
On the product side, merchant onboarding needs KYB, and payment screening needs KYT and sanctions checks regardless of jurisdiction. Identity checks can use the same provider patterns covered in our note on blockchain for KYC. If fiat settlement is part of your model, the banking relationship is often the slowest dependency, which is why founders start early with crypto-friendly banks for business.
Timelines follow the same logic. A narrow QR-payment system we estimated needed one month of discovery and one to two months of development; custom multi-chain gateways run longer. The external security audit is budgeted separately from development. For module-level numbers, infrastructure costs, and audit budgets, see our detailed breakdown of gateway development costs.
Yes. The technical parts are well understood: address management, a blockchain listener, confirmation rules, screening, a ledger, and a merchant API. The harder questions are custody and licensing. If you receive funds and pass them to merchants, US guidance treats you as a money transmitter. If volume is low, integrating an existing processor or starting from a white-label base is usually faster than building everything.
Your backend creates an invoice through the API, the checkout shows address, amount, network, and expiry, and your server waits for a signed webhook such as invoice.paid. Verify the HMAC signature and timestamp, store the event ID to avoid double processing, and fulfill the order only on a final paid status.
Architecturally it is the same loop, narrowed to USDT, USDC, or similar assets on a few networks. The differences are in rate handling, since there is little volatility to manage, and in regulation: in the US, the GENIUS Act affects which payment stablecoins platforms may offer once it takes effect, and in the EU, MiCA rules for e-money tokens play the same role.
Not at the start. A third-party RPC provider is enough for low volume. Own nodes become worth it when volume grows, when provider limits or outages affect payments, or when you need full control over data. If you plan to run them, start synchronization early, because a Bitcoin node can take days to sync.