# How a crypto payment gateway works, step by step

> From a created payment to a payout: checkout page, transfer detection, confirmations, signed webhook and balance — each step of a CryptoLike crypto payment.

Source: https://cryptolike.net/blog/how-crypto-payment-gateway-works
Published: 2026-09-24 · Updated: 2026-10-04 · Author: CryptoLike team

Key takeaways:

- A crypto payment moves through new, pending and paid; underpaid, expired and cancelled cover the other outcomes.
- The checkout page shows the amount, network, address and time left before the payer sends anything.
- Paid means the transfer reached the asset's confirmation threshold and the funds are on your balance.
- Your server learns the result from a signed webhook or from GET /v1/invoices/{id}, then you ship and pay out from the same balance.

A crypto payment gateway sits between a business and the blockchains: it gives the payer an address and an amount, watches the network, decides when the money counts as received and tells the business's systems about it. This article follows one CryptoLike payment from creation to payout, step by step, with the statuses and events your integration sees at each point. For the ways to connect a website, read the guide on [how to accept crypto payments](https://cryptolike.net/guides/accept-crypto-payments).

## What is a crypto payment gateway?

A crypto payment gateway is a service that accepts cryptocurrency on behalf of a business and reports the result in business terms: paid, underpaid, expired. CryptoLike is a crypto payment processing platform: businesses accept Bitcoin, Litecoin, Ethereum, TRON and USDT/USDC stablecoins through a REST API, CMS plugins, payment links and a hosted checkout page, and send payouts from one balance.

Without a gateway, a business would publish its own wallet address, match incoming transfers to orders by hand, count confirmations and convert prices itself. The gateway turns each of those into a field of one object — the payment — with one status, the same in the API, on the checkout page and in webhooks.

How this looks in practice depends on the business: an [online store](https://cryptolike.net/use-cases/online-stores) connects a plugin, a [digital goods or SaaS service](https://cryptolike.net/use-cases/digital-goods) calls the API, and a service with user balances gives each user a [static deposit address](https://cryptolike.net/use-cases/deposits). The steps below are the same for all three. If you are still comparing providers, take the [10 questions to ask a crypto payment gateway](https://cryptolike.net/blog/choose-crypto-payment-gateway) along.

## Step 1. The payment is created

Every CryptoLike payment starts as one object with an amount, a currency and a time limit, created with status `new`. It can be priced in a coin (`USDT`, `BTC`) or in fiat (`USD`, `EUR`). It is created by your server through `POST /v1/invoices`, by a CMS plugin at checkout, or from the cabinet as an invoice or payment link.

The response carries `checkout_url` — the page to send the payer to — and `ttl_expires_at`, the deadline. The time limit is set per payment with `ttl_seconds` (from 60 seconds to 30 days) or taken from your account setting. Two protections stop a retry from creating a second payment: an `Idempotency-Key` header replays the same response for 24 hours, and `idempotency_by_order_id` returns the open payment of an order instead of creating another one.

Other ways to create the same object: a [payment link](https://cryptolike.net/glossary/payment-link) from the cabinet or the Telegram bot, or a [crypto invoice](https://cryptolike.net/glossary/crypto-invoice) sent to a client. All of them lead to the same checkout page.

## Step 2. The payer opens the checkout page

The CryptoLike checkout page shows every critical parameter before the payer acts: the amount to send, the asset and its network, the address with a QR code, and the time left. If you did not fix the asset, the payer first chooses what to pay with from the coins you offer, each with an approximate amount marked ≈; the exchange rate is locked at that moment and does not change until the payment expires. Token icons such as USDT carry a small badge of their network.

Next to the address the page shows a network warning — for example, "Send only BTC on the Bitcoin network to this address. Funds sent on another network cannot be recovered." The status on the page updates live, so the payer does not need to reload it. The page opens as a hosted page or inside your own checkout through the [checkout widget](https://cryptolike.net/docs/widget).

## Step 3. The transfer is detected: pending

As soon as the payer's transfer appears in the network, the CryptoLike payment moves to `pending` and the page says "Payment detected. Waiting for confirmation." The detected amount is shown right away, so a shortfall is visible before any confirmation. The amount is recorded in your `pending` balance, but nothing is available to spend yet: a transfer at this stage can still disappear from the chain.

Your server receives `invoice.pending` with the transaction id in `details`. Do not ship on `pending`; it only tells you the customer has sent something.

## Step 4. Confirmations accumulate

A confirmation is a block built on top of the block that holds the transfer. CryptoLike credits a payment only when the transfer reaches the confirmation threshold of its asset. The threshold is set per asset, published in `GET /v1/currencies` and on the coins page, and shown to the payer as "n of N confirmations, usually about X min".

The threshold protects against block reorganisations, when the network replaces recent blocks and a transfer can vanish. If a reorganisation reverts a transfer that was already confirmed, the payment is recomputed and you receive `invoice.reverted`. The article on [crypto payment confirmations](https://cryptolike.net/blog/crypto-payment-confirmations) explains why thresholds differ between networks; the [coins catalogue](https://cryptolike.net/coins) lists the assets.

## Step 5. Paid, and a signed webhook

When the confirmed amount covers the payment — a shortfall within a small tolerance (0.5 % by default) still counts — CryptoLike sets the status to `paid`, credits the funds to your balance and sends `invoice.paid`. The payer sees "Payment confirmed." and, if you set `return_url`, a link back to your site. `paid` is final: ship the order on it. An overpayment is still `paid`, with `overpaid_amount` above zero.

Each [webhook](https://cryptolike.net/glossary/webhook) is a JSON event signed with HMAC-SHA256 over the timestamp and the raw body; your endpoint verifies the [webhook signature](https://cryptolike.net/glossary/webhook-signature) and answers 2xx within 10 seconds. A delivery that fails is retried after 1 min, 5 min, 15 min, 1 h, 6 h and 24 h, always with the same `event_id`, so your handler stores the id and ignores repeats. Instead of webhooks you can poll `GET /v1/invoices/{id}`, no more often than every few seconds. The full contract is in the [webhooks documentation](https://cryptolike.net/docs/webhooks).

```json
{
  "event_id": "6f1c2c1e-3b2a-4d5e-8f90-1234567890ab",
  "type": "invoice.paid",
  "created_at": "2023-11-14T22:13:20Z",
  "data": { "invoice": { "id": "0e8c9a4b-1111-4222-8333-444455556666", "status": "paid" } }
}
```

## Step 6. The balance and the payout

A confirmed CryptoLike payment lands on your balance of that asset, minus the platform fee: each row of `GET /v1/transactions` shows the gross `amount`, the `fee` and the `net_amount`. The platform fee is charged only when a payment is confirmed and credited; the current schedule is on the [pricing page](https://cryptolike.net/pricing), with an "as of" date.

Balances are kept per asset as `available`, `pending` and `hold`. From `available` you send payouts to external addresses one by one through the API, or in a batch from the cabinet. Ask for an estimate first: it shows the platform fee, the reserved network fee and the total debit before you confirm. Payout addresses can be limited to a [payout whitelist](https://cryptolike.net/glossary/payout-whitelist), and cabinet or Telegram payouts above your threshold can require a second approval. A payout ends as `completed`, or returns the money to `available` as `failed`, `rejected` or `cancelled`.

## Payment statuses at a glance

A CryptoLike payment has six statuses, and the same string appears in the API, on the checkout page and in webhooks. Three are terminal from the start — `paid`, `expired`, `cancelled` — and `underpaid` becomes terminal once the time limit passes; only a CryptoLike operator can reopen an expired or underpaid payment by extending its deadline. The table pairs each status with the event your server receives and the text the payer reads.

| Status | Meaning | Webhook | The payer sees | Terminal |
|---|---|---|---|---|
| `new` | Created; nothing received | `invoice.created` | "Awaiting payment. Send exactly 49.90 USDT to the address below." | no |
| `pending` | A transfer was detected; waiting for confirmations | `invoice.pending` | "Payment detected. Waiting for confirmation." | no |
| `paid` | The amount confirmed, within the underpayment tolerance, and credited | `invoice.paid` | "Payment confirmed." | yes |
| `underpaid` | Less than the amount confirmed, beyond the tolerance; open for a top-up to the same address until the deadline | `invoice.underpaid` | "Partial payment received: 40 of 49.90 USDT. Send the remaining 9.90 USDT to the same address." | after the time limit |
| `expired` | The time limit passed with nothing confirmed | `invoice.expired` | "Payment expired. Create a new payment." | yes |
| `cancelled` | You cancelled it; possible only from `new` | `invoice.cancelled` | "Payment was cancelled by the merchant. Ask the merchant for a new payment if you still want to pay." | yes |

Source: the CryptoLike [status model](https://cryptolike.net/docs#status-model) and the webhook contract, as of 2026-09-24.

## What if the payment does not go to plan?

CryptoLike handles the three common deviations without changing the status model. An underpayment beyond the tolerance becomes `underpaid` with `remaining_amount` and stays open for a top-up; an overpayment is `paid` with `overpaid_amount`; funds that arrive after the payment closed are still credited, with `late_payment: true` and an `invoice.late_payment` event, while the status stays as it was.

Each case has a next step for you and for the payer. The article on [underpaid, overpaid and late crypto payments](https://cryptolike.net/blog/underpaid-crypto-payments) goes through them one by one. For an expired payment the recovery is simple: payment expired — create a new payment.

## FAQ

### What is the difference between a crypto payment gateway and a wallet?

A wallet holds keys and sends or receives transfers. A gateway such as CryptoLike creates a payment for a fixed amount with a deadline, gives the payer an address, counts confirmations and reports the result to your systems by status and signed webhook. You do not run a node or hold keys yourself.

### When should I ship an order?

Ship on `paid`, which comes with `invoice.paid`. `pending` only means a transfer was seen in the network. If a reorganisation later reverts a confirmed transfer, you receive `invoice.reverted`; stop fulfilment until a new `invoice.paid` arrives.

### How does my server learn that a payment is paid?

From a signed webhook (`invoice.paid`) or by reading `GET /v1/invoices/{id}`. Webhooks are delivered at least once and retried with the same `event_id`, so verify the signature, store the id and ignore repeats.

### Can I price a payment in dollars?

Yes. Pass a fiat code such as `USD` in `currency`. The payer chooses the asset on the checkout page from the coins you offer for invoices, the rate is locked at that moment, and the payment stores the fiat amount, the locked rate and the crypto amount.

### Can I test the flow before going live?

Yes. Use test keys and test networks: keys prefixed `ck_test_`, together with the test API URL from CryptoLike support, work with test networks, test coins have no value, and CryptoLike support can send you some. The reference signature vector in the [request signing documentation](https://cryptolike.net/docs/auth) tells you in one call whether your request signing is right.
