Skip to content

Coins & networksGuide

How to accept Bitcoin payments on a website

Accept BTC with CryptoLike step by step: price in BTC or USD, set a deadline that fits Bitcoin's block time, handle slow and replaced transfers, and pay out.

To accept Bitcoin on a website with CryptoLike, create a payment for the order with POST /v1/invoices and the BTC coin_id, send the customer to the payment page, and ship when the payment becomes paid. What makes Bitcoin different from other assets is time: blocks come every 10 minutes on average, the payer's fee decides how soon their transfer gets into one, and your deadline has to allow for both. This guide goes step by step, with the Bitcoin-specific decisions at each step.

Bitcoin payments at a glance

CryptoLike accepts native bitcoin on the Bitcoin network, on-chain. Every payment gets its own address, the status moves from new to pending when the transfer is in a block and to paid at the confirmation threshold of the asset, and a signed webhook reports each change.

Fact Bitcoin on CryptoLike
Asset · network BTC · Bitcoin; network in the API is btc
Precision 8 decimals (1 satoshi = 0.00000001 BTC)
Payment address Native SegWit, starts with bc1q, new for every payment, never reused
Payment URI and QR bitcoin:<address>?amount=<BTC> — the payer's wallet fills in the amount
When pending appears When the transfer is in a block (its first confirmation)
When paid At the confirmation threshold of the asset: confirmations in GET /v1/currencies, shown on the Bitcoin page
Block interval 10 minutes on average, by the network's design
Payout destinations Addresses starting with 1, 3, bc1q or bc1p
Not supported Lightning payments; bitcoin-pegged tokens on other networks

Checked against CryptoLike and the Bitcoin developer documentation on 2026-09-24.

Before you start

You need a CryptoLike account with Bitcoin enabled, an API key with create_invoice and read, and a webhook endpoint on your server that verifies signatures. If your site runs WooCommerce, OpenCart, PrestaShop or Magento, the plugin does steps 2–5 for you — see integrations — and only the deadline advice below applies.

Signing requests is shown in the Node.js guide, the PHP guide and the Python guide. The examples here reuse the cryptolike() helper from the Node.js guide.

1. Choose how you price and how long the customer has

CryptoLike can price a Bitcoin payment in BTC or in a fiat currency. In BTC, the amount is what you type. In USD or EUR, the rate is locked when the payment is created with the BTC coin_id and holds until the deadline, so the BTC amount on the page does not move while the customer pays. How that works: pricing in USD, getting paid in crypto.

The deadline matters more for Bitcoin than for faster networks. A payment that is new or pending at its deadline becomes expired, even if the transfer is already in a block. Money that confirms later is still credited, as a late payment — but the order no longer moves to paid on its own. Size the deadline for three things:

  1. The customer's time to open a wallet and send, often longer when they buy bitcoin on an exchange first.
  2. The first block. 10 minutes on average, but single blocks can take much longer, and a transfer with a low fee can wait for several blocks.
  3. The confirmations. The threshold from GET /v1/currencies times about 10 minutes.

With ttl_seconds you set it per payment, from 60 seconds to 30 days; without it your account default applies, 30 minutes unless changed. For Bitcoin, a deadline of a few hours avoids most late payments; for a price in USD, remember that a longer deadline means a longer rate lock.

2. Find Bitcoin in the catalogue

Take the entry with ticker BTC and network btc from GET /v1/currencies. Its id is the coin_id for payments and payouts, confirmations is the threshold for crediting, and maintenance: true means the asset temporarily cannot be chosen for new payments.

ts
const { currencies } = await cryptolike("GET", "/v1/currencies");
const btc = currencies.find((c: any) => c.ticker === "BTC" && c.network === "btc");
if (!btc || btc.maintenance) throw new Error("Bitcoin is not available right now");

If the entry is missing, Bitcoin is switched off for your account: turn it on in the cabinet on the Coins page. Ask support only if Bitcoin is not offered there at all; until then, offer the customer another asset.

3. Create the payment for the order

Create one payment per order, with the order number as order_id and as the idempotency key, so a double click or a retry never opens a second payment. This example prices the order in US dollars, gives the customer three hours, and fixes the asset to Bitcoin.

ts
const payment = await cryptolike("POST", "/v1/invoices", {
  amount: "129.00",
  currency: "USD",
  coin_id: btc.id,
  order_id: "A-1003",
  idempotency_by_order_id: true,
  ttl_seconds: 3 * 3600,
  return_url: "https://shop.example/orders/A-1003",
}, "order-A-1003");
// payment.address      → bc1q…
// payment.payer_amount → the exact BTC amount to send
// payment.checkout_url → the payment page for the customer

Store payment.id with the order. A 503 unavailable means no fresh BTC rate was available: retry with the same key, or price the payment in BTC. Leave coin_id out if the customer may choose between Bitcoin and other assets on the payment page.

4. Send the customer to the payment page

Redirect the customer to checkout_url, or embed the same page with the checkout widget. The page shows the BTC amount, the network, the bc1q address with a QR code, a warning to send only on the Bitcoin network and the time left. The QR code and the "open in wallet" link carry a bitcoin: URI with the amount, so most wallets fill in both the address and the amount.

Two things the payer should know, and your support should repeat if asked:

  • Send the exact amount, on the Bitcoin network. If a wallet or exchange takes its fee out of the amount, the payment arrives short; a shortfall of more than 0.5 % of the amount makes it underpaid, a smaller one still counts as paid. The payer can top up to the same address before the deadline.
  • The network fee is on top. The payer's wallet chooses the fee in satoshis per virtual byte; a higher fee usually gets the transfer into a block sooner. CryptoLike does not set it and does not receive it.

5. Wait for confirmations and ship on paid

CryptoLike watches the Bitcoin blockchain block by block. When a block includes the transfer, the payment becomes pending — "Payment detected. Waiting for confirmation." — and your endpoint receives invoice.pending. Each new block adds a confirmation; at the threshold the payment is paid, the funds are credited, and invoice.paid arrives. Ship on invoice.paid, not before.

Transfers that are only in the mempool — broadcast but not yet in a block — are not shown as pending. This is deliberate: until a transfer is in a block it can still be replaced, and showing it would promise a payment that may never arrive. The customer sees the page update as soon as the first block includes the transfer. Why the threshold differs between networks is explained in how many confirmations a crypto payment needs.

If a block reorganisation removes a confirmed transfer from the chain, CryptoLike reverses the credit and sends invoice.reverted. Stop fulfilment until a new invoice.paid arrives. More about reorgs.

6. Handle slow, replaced and late transfers

Bitcoin transfers can be slow or can change before they confirm, and your order logic needs an answer for each case. None of them needs special code on your side: the payment's status and webhooks already express them.

What happened What CryptoLike does What you do
Transfer with a low fee waits for a block Nothing is shown until it is in a block Nothing; if the deadline passes first, see "late" below
The payer replaced the transfer (replace-by-fee) before a block Only the transfer that reaches a block counts Nothing: the replacement is credited if it pays the address
The replacement sends the coins elsewhere Nothing arrives at the payment The payment expires; the customer pays again with a new payment
Transfer confirmed after the deadline Credited to your balance, late_payment: true, invoice.late_payment Decide with the customer: fulfil or refund
More than 0.5 % less than the amount underpaid; the payer can top up until the deadline Wait, then ship for less, ask for the rest or refund

The last two rows are covered in detail in underpaid, overpaid and late payments.

7. Pay out bitcoin

Payouts in BTC go from your available balance with POST /v1/withdrawals, to standard Bitcoin addresses: legacy (1…), script (3…), native SegWit (bc1q…) or Taproot (bc1p…). Call POST /v1/withdrawals/estimate first: it returns the platform fee, the reserved network fee, the total debit and the minimum amount, all in BTC, before anything is created.

The network fee of a Bitcoin payout is based on the fee rate the network currently needs for confirmation within a few blocks. The estimate reserves it with a safety margin; depending on the mode the platform sets for your account, you pay the reserve, or the fee actually paid with the rest returned. Send your own payout_id so a retried request never pays twice, and protect regular destinations with the payout whitelist and second approval. The fee schedule is on the pricing page.

Errors and what to do

HTTP · code What happened What to do
400 validation_error, field amount More than 8 decimals, or not a positive number Round to satoshis and resend
409 conflict, order_invoice_mismatch The order has an open payment with another amount Reuse it, or cancel it while it is still new and create a new one
503 unavailable No fresh BTC rate for a fiat-priced payment Retry with the same Idempotency-Key, or price in BTC
422 address_refused on a payout The destination is not accepted Use another address
403 kyb_required on a payout Payouts need a verified account Complete account verification in the cabinet

All codes are listed in the API reference.

FAQ

How long does a Bitcoin payment take to confirm?

Bitcoin produces a block every 10 minutes on average, and CryptoLike credits BTC at the confirmation threshold of the asset, published in GET /v1/currencies. The payment becomes pending when the first block includes the transfer. A low network fee can delay that first block.

Why doesn't the payment page show my transfer right away?

CryptoLike shows a Bitcoin transfer once a block includes it. A transfer that is only broadcast can still be replaced or dropped, so it is not shown as pending. If the payer set a low fee, the first block may take longer; the page updates as soon as it arrives.

What deadline should I set for Bitcoin payments?

Allow time for the customer to send, for the first block and for the confirmations. A payment that is still new or pending at its deadline expires, and money that confirms later arrives as a late payment. A deadline of a few hours avoids most late payments.

Can customers pay with Lightning?

No. CryptoLike accepts on-chain bitcoin on the Bitcoin network only. Lightning payments and bitcoin-pegged tokens on other networks do not reach the payment. Customers who hold stablecoins can pay in USDT on TRON or Ethereum instead.

Are Bitcoin payment addresses reused?

No. Every payment gets a new native SegWit address starting with bc1q, and an address index is never reused. That is how a transfer is matched to exactly one payment without asking the payer for a reference.

Terms used here

Read next

Start with a test payment

Create an account, ask support for the test environment and see a payment go from pending to paid on a test network.