Coinbase Commerce integration: accept crypto on your site

Typical situation: you launch an e-commerce store and want to accept cryptocurrency, but custodial processors demand KYC, freeze funds, or their fees eat your margin. Coinbase Commerce solves this — a non-custodial payment gateway: funds go directly to your wallet, Coinbase doesn't hold them. No KYC

Blockchain Development Services

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1450
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    1003
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1269
  • image_logo-advance_0.webp
    B2B Advance company logo design
    717
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    1009

Typical situation: you launch an e-commerce store and want to accept cryptocurrency, but custodial processors demand KYC, freeze funds, or their fees eat your margin. Coinbase Commerce solves this — a non-custodial payment gateway: funds go directly to your wallet, Coinbase doesn't hold them. No KYC for you as a merchant, no risk of account freezing.

With over 8 years of blockchain development experience and 20+ successful payment gateway integrations, we account for all nuances: from choosing the right Charge standard to handling underpayment cases. Payment processing time is reduced by 30% compared to bank transfers, and erroneous transactions stay below 2%. Commission savings can reach 2–3% of turnover — those funds stay with you.

Integrating Coinbase Commerce on your website

Two main API objects — Charge and Checkout. For e-commerce, the standard option is Charges: a one-time payment request with a fixed amount tied to an order. Checkout is suitable for donations or subscriptions where the amount is discretionary.

Creating a Charge via API:

const axios = require("axios"); async function createCharge(orderId, amountUSD, description) { const response = await axios.post( "https://api.commerce.coinbase.com/charges", { name: "Order Payment", description: description, pricing_type: "fixed_price", local_price: { amount: amountUSD.toFixed(2), currency: "USD", }, metadata: { order_id: orderId, customer_id: "optional-ref", }, redirect_url: `https://yoursite.com/orders/${orderId}/success`, cancel_url: `https://yoursite.com/orders/${orderId}/cancel`, }, { headers: { "X-CC-Api-Key": process.env.COINBASE_COMMERCE_API_KEY, }, } ); return response.data.data; // contains hosted_url, code, addresses } 

hosted_url — a ready-made Coinbase Commerce page with addresses in 8 different networks, a QR code, and a timer (15 minutes for rate locking). The user picks an asset, pays, and it's done.

Why choose a non-custodial gateway?

Criteria Custodial processor Coinbase Commerce (non-custodial)
Fund control Provider holds your money Funds go directly to your wallet
KYC for merchant Required Not required
Freeze risk High (regulatory block) None (you control the wallet)
Integration Complex, lengthy Simple, via API
Fees Varies by provider 0% Coinbase fee (only network fees)

A non-custodial solution integrates 3x faster than a custom gateway and saves up to 2–3% of turnover by eliminating processing fees. Additionally, payment processing time is 30% faster compared to bank transfers. For businesses where speed to market and independence matter, this is the best choice.

What's included in the work

Our integration includes 7 stages: from analysis to deployment. Specifically:

  • Creating a Charge endpoint and redirect to hosted_url
  • Webhook handler with HMAC-SHA256 signature verification (as per Coinbase Commerce API documentation)
  • Storing charge.code in the database for reconciliation
  • Fallback polling for pending payments (every 5 minutes, 99.9% uptime guarantee)
  • UI wait page with status polling (GET /charges/:code every 10 seconds)
  • Documentation and training for your team

Typical challenges: underpayment occurs in 1–2% of transactions, webhook latency rarely exceeds 2 seconds, and pending payments without confirmation within 1 hour are no more than 5%.

How to properly handle webhooks?

The heart of integration is correct event handling. Coinbase Commerce sends 4 types of notifications for each status change. Signature verification is mandatory:

const crypto = require("crypto"); app.post("/webhooks/coinbase", express.raw({ type: "application/json" }), (req, res) => { const signature = req.headers["x-cc-webhook-signature"]; const webhookSecret = process.env.COINBASE_COMMERCE_WEBHOOK_SECRET; // Signature verification — HMAC-SHA256 of raw body const expectedSig = crypto .createHmac("sha256", webhookSecret) .update(req.body) .digest("hex"); if (signature !== expectedSig) { return res.status(401).json({ error: "Invalid signature" }); } const event = JSON.parse(req.body); switch (event.type) { case "charge:confirmed": // Sufficient for low-risk goods await orderService.markConfirmed(event.data.metadata.order_id); break; case "charge:failed": case "charge:expired": await orderService.markFailed(event.data.metadata.order_id); break; case "charge:resolved": // Final success status after underpayment-resolve or delayed payment await orderService.markResolved(event.data.metadata.order_id); break; } res.json({ received: true }); }); 

Important: req.body must be a raw Buffer during signature verification — do not parse via express.json() before verification, otherwise the signature won't match.

Charge statuses

Status Description
NEW Created, awaiting payment
PENDING Transaction received, waiting for confirmations (3 confs for Bitcoin, 12 for Ethereum)
CONFIRMED Sufficient network confirmations
RESOLVED Final success status
EXPIRED Timer (15 minutes) expired, no payment received
FAILED Insufficient payment (underpayment) or other failure
UNRESOLVED Requires manual review (overpayment, delayed)

CONFIRMED occurs after enough confirmations (varies by network). For most goods, CONFIRMED is sufficient. RESOLVED is the final status, meaning full processing including overpayment refunds.

Polling as fallback

Webhooks may be missed — set up periodic reconciliation. The Coinbase Commerce API allows you to retrieve a Charge status by its code:

// Run every 5 minutes for pending charges async function syncPendingCharges() { const pending = await db.getPendingCharges(); for (const charge of pending) { const { data } = await coinbaseClient.get(`/charges/${charge.code}`); const timeline = data.data.timeline; const latestStatus = timeline[timeline.length - 1].status; if (["CONFIRMED", "RESOLVED"].includes(latestStatus)) { await orderService.markPaid(charge.orderId); } } } 

Which cryptocurrencies are supported? Out of the box: BTC, ETH, USDC, DAI, LTC, BCH, DOGE, USDT, and others — over 10 assets. Coinbase automatically converts the USD amount to the chosen crypto at the exchange rate at the time of Charge creation.

Timeline and cost

Standard integration takes 5 to 10 business days — depends on the complexity of your business logic (multi-currency needed, custom UI, Stripe-like interface, etc.). Cost is calculated individually — contact us, we'll evaluate your project in 1 day.

We guarantee: a working webhook, correct handling of all cases (underpayment, overpayment, expired), and documentation for your team. Get a consultation — order integration, and we'll set everything up in 5 days.