Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Coinbase API

Bolt.new supports two Coinbase integrations: Coinbase Commerce for accepting Bitcoin, Ethereum, and USDC payments via hosted checkout, and Coinbase Advanced Trade API for live crypto prices and portfolio tracking. Commerce charge creation works in Bolt's WebContainer using coinbase-commerce-node. API keys go in .env. Commerce webhooks for payment confirmation require a deployed URL on Netlify or Bolt Cloud — test the full payment flow there.

What you'll learn

  • How to create a Coinbase Commerce account and generate API credentials
  • How to create crypto payment charges and hosted checkout links from a Next.js API route
  • How to fetch real-time cryptocurrency prices using the Coinbase Advanced Trade API
  • How to display a crypto price ticker and portfolio tracker in React
  • How to handle Commerce webhooks for payment confirmation after deployment
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate17 min read25 minutesPaymentApril 2026RapidDev Engineering Team
TL;DR

Bolt.new supports two Coinbase integrations: Coinbase Commerce for accepting Bitcoin, Ethereum, and USDC payments via hosted checkout, and Coinbase Advanced Trade API for live crypto prices and portfolio tracking. Commerce charge creation works in Bolt's WebContainer using coinbase-commerce-node. API keys go in .env. Commerce webhooks for payment confirmation require a deployed URL on Netlify or Bolt Cloud — test the full payment flow there.

Accept Crypto Payments and Display Live Prices with Coinbase in Bolt.new

Coinbase's developer APIs split into two distinct products that serve different use cases in a Bolt.new app. Coinbase Commerce is the payment processing side: it generates hosted checkout pages where customers pay in Bitcoin, Ethereum, Litecoin, USDC, DAI, or other supported cryptocurrencies. You create a 'charge' via API, receive a hosted checkout URL, and redirect the customer there. Commerce handles the crypto wallet address generation, payment monitoring, exchange rate conversion, and underpayment handling. For non-technical founders building apps that want to accept crypto without dealing with blockchain complexity, Commerce is dramatically simpler than building raw crypto payment flows.

Coinbase Advanced Trade API (formerly Coinbase Pro API) is the market data side: it provides real-time and historical price data, order books, candlestick charts, and for authenticated users, portfolio balances and trading. If you are building a price dashboard, portfolio tracker, crypto calculator, or any feature that displays cryptocurrency prices, this is the API to use. The public market data endpoints require no authentication — you can fetch prices without any API key at all for basic use cases.

Both APIs communicate over HTTPS with JSON responses, making them fully compatible with Bolt.new's WebContainer. The `coinbase-commerce-node` npm package is pure JavaScript with no native binary dependencies and installs in the WebContainer. Outbound price requests to the Advanced Trade API work from both React components (for public endpoints) and API routes (for authenticated endpoints). The one capability that requires deployment is Commerce webhooks — Coinbase sends a POST request to your app when a payment is confirmed, and this incoming connection cannot reach the WebContainer preview URL.

Integration method

Bolt Chat + API Route

Bolt generates a Next.js API route that creates Coinbase Commerce charges and fetches crypto price data server-side, keeping your API keys out of client bundles. The coinbase-commerce-node package is pure JavaScript and works in Bolt's WebContainer for charge creation. Real-time price polling with the Advanced Trade API also works in the preview. Commerce webhooks for payment confirmation require a deployed URL — the WebContainer cannot receive incoming webhook callbacks from Coinbase.

Prerequisites

  • A Bolt.new account with a Next.js project
  • For Commerce: a Coinbase Commerce account (commerce.coinbase.com) with Commerce API key
  • For price data: no account required — public Advanced Trade API endpoints are unauthenticated
  • For authenticated portfolio tracking: a Coinbase account with Advanced Trade API key (CDP Portal at portal.cdp.coinbase.com)

Step-by-step guide

1

Set Up Coinbase Commerce and Get API Credentials

For accepting cryptocurrency payments, start with Coinbase Commerce — it is separate from the main Coinbase exchange and designed specifically for merchants. Go to commerce.coinbase.com and sign up with your email address. You do not need an existing Coinbase exchange account; Commerce is a standalone service. Complete the merchant setup including your business name and optionally connecting a bank account for USD payouts (optional for getting started). Once logged in to Commerce, go to Settings > Security and scroll to 'API keys.' Click 'Create an API Key.' Coinbase generates a Commerce API key that looks like a UUID string. Copy it immediately — like most API keys, it is only shown once at creation. This key authenticates your server-side requests to create charges, list payments, and manage products. For the Coinbase Advanced Trade API (price data and portfolio), the setup is different. Go to portal.cdp.coinbase.com (Coinbase Developer Platform). Navigate to 'API Keys' and click 'Create API Key.' Advanced Trade API uses a newer JWT-based authentication system: you get an API Key Name (a string like 'organizations/{id}/apiKeys/{id}') and a private key (an EC private key in PEM format). Store both securely — the private key is used to sign JWT tokens for each request. For public market data (prices without account access), you do not need any API key at all and can call the public endpoints directly.

Pro tip: Coinbase Commerce and Coinbase Advanced Trade API are completely separate products with separate accounts and credentials. You can use one without the other depending on your use case.

Expected result: You have a Coinbase Commerce API key for payment processing and optionally a Coinbase Advanced Trade API key pair for authenticated account access.

2

Install coinbase-commerce-node and Create Charge Endpoint

The `coinbase-commerce-node` package is the official Node.js SDK for Coinbase Commerce. It is a pure JavaScript library with no native binary dependencies — it installs and runs without issues in Bolt's WebContainer. Install it from the Bolt terminal: in Bolt's terminal panel, run `npm install coinbase-commerce-node`. The installation completes in a few seconds from the CDN-backed package cache. With the package installed, create a Next.js API route that generates Commerce charges. A charge is a payment request for a specific amount in a fiat currency (USD, EUR, etc.) that Coinbase Commerce converts to the equivalent crypto amount at the time of payment. The charge response includes a `hosted_url` — this is the Coinbase-hosted checkout page URL where you redirect the customer to complete payment. The charge creation payload includes the `name` (product or service name displayed on the checkout), `description`, `pricing_type` (always 'fixed_price' for a specific amount), and `local_price` with the amount and currency. Optionally include `redirect_url` (where Coinbase redirects after payment) and `cancel_url` (where Coinbase redirects if the user cancels). Both of these redirect URLs should be your deployed app URLs for production — during development you can use any URL since the redirect happens in the user's browser after they complete payment on Coinbase's hosted page. The Commerce SDK's `Charge.create()` method handles the HTTP request and response parsing. The result is a charge object with `id`, `code`, `hosted_url`, `expires_at`, and `addresses` (the crypto wallet addresses Coinbase generated for this payment).

Bolt.new Prompt

Install coinbase-commerce-node with npm. Create a Next.js API route at app/api/crypto/commerce/route.ts that creates a Coinbase Commerce charge using the Client from coinbase-commerce-node. Accept POST requests with { amount, currency, productName, description } in the request body. Initialize the Commerce client with COINBASE_COMMERCE_API_KEY from process.env. Return the charge id, code, hosted_url, and expires_at.

Paste this in Bolt.new chat

app/api/crypto/commerce/route.ts
1// app/api/crypto/commerce/route.ts
2import { NextResponse } from 'next/server';
3// @ts-ignore — coinbase-commerce-node types are legacy
4import { Client, resources } from 'coinbase-commerce-node';
5
6const { Charge } = resources;
7
8// Initialize Commerce client
9Client.init(process.env.COINBASE_COMMERCE_API_KEY || '');
10
11export async function POST(request: Request) {
12 try {
13 const { amount, currency = 'USD', productName, description } = await request.json();
14
15 if (!amount || !productName) {
16 return NextResponse.json(
17 { error: 'amount and productName are required' },
18 { status: 400 }
19 );
20 }
21
22 const chargeData = {
23 name: productName,
24 description: description || productName,
25 pricing_type: 'fixed_price',
26 local_price: {
27 amount: String(amount),
28 currency: currency,
29 },
30 // Redirect URLs for after payment — use your deployed URL in production
31 redirect_url: process.env.NEXT_PUBLIC_APP_URL
32 ? `${process.env.NEXT_PUBLIC_APP_URL}/payment/success`
33 : undefined,
34 cancel_url: process.env.NEXT_PUBLIC_APP_URL
35 ? `${process.env.NEXT_PUBLIC_APP_URL}/payment/cancelled`
36 : undefined,
37 };
38
39 const charge = await Charge.create(chargeData);
40
41 return NextResponse.json({
42 id: charge.id,
43 code: charge.code,
44 hosted_url: charge.hosted_url,
45 expires_at: charge.expires_at,
46 // Do not expose the full charge object — it contains sensitive wallet addresses
47 });
48 } catch (err) {
49 const message = err instanceof Error ? err.message : 'Charge creation failed';
50 return NextResponse.json({ error: message }, { status: 500 });
51 }
52}

Pro tip: Coinbase Commerce charges expire after 60 minutes by default. Do not create a charge until the user actually clicks the payment button — generating speculative charges wastes your Commerce account's charge history.

Expected result: The Commerce API route creates charges successfully. Testing with a POST request returns a hosted_url you can open in a browser to see Coinbase's crypto checkout page.

3

Build the Crypto Price Dashboard with Advanced Trade API

Coinbase Advanced Trade API's public market data endpoints require no authentication. You can fetch current prices, 24-hour statistics, and order book data for any supported trading pair without an API key. This makes it straightforward to build public-facing price dashboards directly from API calls. The key endpoint is `GET https://api.coinbase.com/api/v3/brokerage/market/products/{product_id}` for individual product stats, or you can fetch multiple products at once. The response includes `price` (last trade price), `price_percentage_change_24h`, `volume_24h`, `high_52_week`, `low_52_week`, and more. Product IDs follow the format `{BASE}-{QUOTE}` — for Bitcoin priced in US dollars it is `BTC-USD`. For public endpoints, you can call the Advanced Trade API directly from a React component or from an API route. Using an API route is still recommended because it avoids potential CORS issues in different browser configurations and allows you to add caching. Implement a polling interval in the React component using `useEffect` with a `setInterval` — refresh every 30-60 seconds for live price data. Exponential backoff in error handling prevents hammering the API during outages. For authenticated endpoints (portfolio balances, order history), Advanced Trade API uses JWT authentication. Each request must include a JWT token signed with your EC private key, with a short expiration. The `@coinbase/coinbase-sdk` package handles this signing automatically. Authenticated requests must go through your API route — the private key must never appear in client-side code.

Bolt.new Prompt

Build a crypto price ticker component. Create a Next.js API route at /api/crypto/prices that fetches current price data for BTC-USD, ETH-USD, SOL-USD, DOGE-USD, and USDC-USD from Coinbase Advanced Trade API public endpoints (no auth needed). Return price, price_percentage_change_24h, and volume_24h. Build a React PriceTicker component that calls this every 30 seconds and displays each coin with its logo emoji, current price formatted as USD, and 24h change with green/red coloring.

Paste this in Bolt.new chat

app/api/crypto/prices/route.ts
1// app/api/crypto/prices/route.ts
2import { NextResponse } from 'next/server';
3
4const PRODUCTS = ['BTC-USD', 'ETH-USD', 'SOL-USD', 'DOGE-USD', 'USDC-USD'];
5
6// Simple in-memory cache to reduce Coinbase API calls
7let priceCache: { data: unknown; timestamp: number } | null = null;
8const CACHE_TTL = 15_000; // 15 seconds
9
10export async function GET() {
11 if (priceCache && Date.now() - priceCache.timestamp < CACHE_TTL) {
12 return NextResponse.json(priceCache.data);
13 }
14
15 try {
16 const results = await Promise.all(
17 PRODUCTS.map(async (productId) => {
18 const res = await fetch(
19 `https://api.coinbase.com/api/v3/brokerage/market/products/${productId}`,
20 { headers: { 'Content-Type': 'application/json' } }
21 );
22 if (!res.ok) throw new Error(`Failed to fetch ${productId}`);
23 return res.json();
24 })
25 );
26
27 const prices = results.map((product) => ({
28 id: product.product_id,
29 price: parseFloat(product.price || '0'),
30 change24h: parseFloat(product.price_percentage_change_24h || '0'),
31 volume24h: parseFloat(product.volume_24h || '0'),
32 high52w: parseFloat(product.high_52_week || '0'),
33 low52w: parseFloat(product.low_52_week || '0'),
34 }));
35
36 priceCache = { data: { prices, updatedAt: new Date().toISOString() }, timestamp: Date.now() };
37 return NextResponse.json(priceCache.data);
38 } catch (err) {
39 const message = err instanceof Error ? err.message : 'Failed to fetch prices';
40 // Return stale cache on error if available
41 if (priceCache) return NextResponse.json(priceCache.data);
42 return NextResponse.json({ error: message }, { status: 500 });
43 }
44}

Pro tip: Cache price responses for at least 15 seconds. Coinbase Advanced Trade's public endpoints have rate limits, and polling faster than once per 10 seconds provides minimal benefit for display purposes.

Expected result: The price ticker displays live cryptocurrency prices for BTC, ETH, SOL, DOGE, and USDC with 24h change percentages updating every 30 seconds in Bolt's preview.

4

Configure Environment Variables

Add your Coinbase credentials to the `.env` file in your Bolt project root. The variable naming convention depends on which Coinbase products you are using. Commerce uses a single API key. Advanced Trade API authenticated calls require both an API key name and a private key — the private key is a multi-line PEM string which requires careful handling in environment variables. For Coinbase Advanced Trade private keys in .env, the PEM format contains newlines. When storing a PEM key in a single-line environment variable, replace the newline characters with `\n` literal characters — your server-side code then replaces them back when constructing the key. Alternatively, use Bolt Cloud's Secrets manager for multi-line values, which handles the encoding automatically. The `NEXT_PUBLIC_APP_URL` variable enables proper redirect URL configuration for Commerce charges. During development, this can be blank (redirects will use the Commerce page's default behavior). After deployment, set it to your Netlify URL so Commerce redirects users back to your app after payment.

Bolt.new Prompt

Update the .env file with Coinbase environment variables: COINBASE_COMMERCE_API_KEY for Commerce, COINBASE_API_KEY_NAME and COINBASE_PRIVATE_KEY for Advanced Trade API, and NEXT_PUBLIC_APP_URL. Add validation in the API routes to check that required env vars are present and return a clear error message if they are missing.

Paste this in Bolt.new chat

.env
1# .env
2# Coinbase Commerce (for accepting crypto payments)
3COINBASE_COMMERCE_API_KEY=your-commerce-api-key
4
5# Coinbase Advanced Trade API (for price data and portfolio optional)
6COINBASE_API_KEY_NAME=organizations/your-org-id/apiKeys/your-key-id
7COINBASE_PRIVATE_KEY="-----BEGIN EC PRIVATE KEY-----\nYOUR_PRIVATE_KEY_HERE\n-----END EC PRIVATE KEY-----"
8
9# App URL for Commerce redirects (set to deployed URL in production)
10NEXT_PUBLIC_APP_URL=https://your-app.netlify.app

Pro tip: The COINBASE_PRIVATE_KEY for Advanced Trade API must have its newlines escaped as \n in the .env file. In your API route, restore them with: privateKey.replace(/\\n/g, '\n')

Expected result: Environment variables are configured. Commerce charge creation works in the preview. Price fetching works without authentication for public endpoints.

5

Deploy and Configure Commerce Webhooks

Coinbase Commerce webhooks are the mechanism by which your app learns that a payment has been confirmed. When a customer pays, Coinbase monitors the blockchain, waits for sufficient confirmations, and then sends a POST request to your webhook URL with a signed event payload. Without webhooks, your app has no reliable way to know that payment succeeded — you would have to poll the Commerce API repeatedly. Because Coinbase sends an incoming HTTP POST to your app, webhooks cannot be received in Bolt's WebContainer preview. The WebContainer has no way to accept incoming connections from the internet. Deploy your app to Netlify or Bolt Cloud first to get a stable HTTPS URL. After deployment, go to your Coinbase Commerce dashboard > Settings > Notifications. Click 'Add an endpoint' and enter your webhook URL (e.g., `https://your-app.netlify.app/api/crypto/webhook`). Coinbase generates a webhook signing secret — copy this and add it to your Netlify environment variables as `COINBASE_COMMERCE_WEBHOOK_SECRET`. Your webhook handler verifies this signature on every incoming event to confirm it genuinely came from Coinbase. The most important Commerce event is `charge:confirmed` — this fires when a payment has received enough blockchain confirmations to be considered final. Also handle `charge:failed` (payment not received before the 60-minute expiry), `charge:delayed` (payment received but under-confirmed — wait for confirmed event), and `charge:pending` (transaction broadcast but awaiting confirmations).

Bolt.new Prompt

Create a Coinbase Commerce webhook handler at app/api/crypto/webhook/route.ts. It should verify the X-CC-Webhook-Signature header using HMAC-SHA256 with COINBASE_COMMERCE_WEBHOOK_SECRET from process.env. Handle these events: charge:confirmed (mark order as paid), charge:failed (mark order as failed), charge:pending (mark as pending). Return 200 immediately. Note in comments that this route requires the deployed URL — it will not receive webhooks in the Bolt WebContainer preview.

Paste this in Bolt.new chat

app/api/crypto/webhook/route.ts
1// app/api/crypto/webhook/route.ts
2// IMPORTANT: This webhook handler requires a deployed URL.
3// Coinbase Commerce cannot send webhooks to Bolt's WebContainer preview URL.
4// Deploy to Netlify or Bolt Cloud, then register the deployed URL in Commerce Settings.
5import { NextResponse } from 'next/server';
6import crypto from 'crypto';
7
8export async function POST(request: Request) {
9 const rawBody = await request.text();
10 const signature = request.headers.get('X-CC-Webhook-Signature');
11 const secret = process.env.COINBASE_COMMERCE_WEBHOOK_SECRET;
12
13 if (!secret) {
14 console.error('COINBASE_COMMERCE_WEBHOOK_SECRET is not configured');
15 return NextResponse.json({ error: 'Webhook secret not configured' }, { status: 500 });
16 }
17
18 // Verify webhook signature
19 const expectedSignature = crypto
20 .createHmac('sha256', secret)
21 .update(rawBody)
22 .digest('hex');
23
24 if (signature !== expectedSignature) {
25 console.error('Invalid Commerce webhook signature');
26 return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
27 }
28
29 const event = JSON.parse(rawBody);
30 const { type, data } = event;
31 const chargeCode = data?.object?.code;
32
33 console.log(`Commerce webhook: ${type} for charge ${chargeCode}`);
34
35 switch (type) {
36 case 'charge:confirmed':
37 // Payment confirmed — fulfill the order
38 // e.g., update your database, send confirmation email, grant access
39 console.log(`Payment confirmed for charge ${chargeCode}`);
40 break;
41 case 'charge:failed':
42 // Payment failed or expired — handle appropriately
43 console.log(`Charge failed: ${chargeCode}`);
44 break;
45 case 'charge:pending':
46 // Transaction broadcast, awaiting confirmations
47 console.log(`Charge pending: ${chargeCode}`);
48 break;
49 case 'charge:delayed':
50 // Payment received after expiry — manual review needed
51 console.log(`Delayed payment for charge: ${chargeCode}`);
52 break;
53 }
54
55 // Always return 200 quickly — Coinbase will retry on non-200 responses
56 return NextResponse.json({ received: true });
57}

Pro tip: Always return a 200 response quickly from webhook handlers. If your payment confirmation logic takes time (database writes, emails), process it asynchronously after returning 200 to avoid Coinbase retry storms.

Expected result: The webhook handler is deployed and registered in Coinbase Commerce. Test payments show confirmed events arriving at the endpoint. The Netlify function logs show the webhook events being processed.

Common use cases

Crypto Payment Button

Add a 'Pay with Crypto' button to any Bolt-built app. Clicking it creates a Coinbase Commerce charge via your API route and redirects the user to Coinbase's hosted checkout page. The checkout page accepts multiple cryptocurrencies and shows a QR code and wallet address. After payment confirmation, Coinbase Commerce triggers a webhook to update the payment status in your app.

Bolt.new Prompt

Add a Coinbase Commerce payment button to my app. Create a Next.js API route at /api/crypto/checkout that uses coinbase-commerce-node to create a Commerce charge for a given amount in USD. The charge should accept Bitcoin, Ethereum, and USDC. Return the hosted_url to redirect the user to Coinbase's payment page. Add a 'Pay with Crypto' button component that calls this endpoint and redirects. Store COINBASE_COMMERCE_API_KEY in process.env.

Copy this prompt to try it in Bolt.new

Live Crypto Price Dashboard

Build a real-time cryptocurrency price ticker showing BTC, ETH, SOL, and other coins with 24-hour price change percentages and sparkline charts. Fetches data from Coinbase Advanced Trade's public market data endpoints every 30 seconds. No API key required for public price data — perfect for customer-facing price displays.

Bolt.new Prompt

Build a crypto price dashboard using Coinbase Advanced Trade API. Create a Next.js API route at /api/crypto/prices that fetches current prices and 24h stats for BTC-USD, ETH-USD, SOL-USD, and USDC-USD from Coinbase's public market data endpoint at https://api.coinbase.com/api/v3/brokerage/market/products. Display results as price cards with current price, 24h change percentage (green if positive, red if negative), and 24h high/low. Refresh every 30 seconds.

Copy this prompt to try it in Bolt.new

Portfolio Tracker with Authenticated Balance

Build a personal crypto portfolio tracker that shows Coinbase account balances, recent transactions, and total portfolio value in USD. Requires Coinbase Advanced Trade API authentication with an API key and secret (JWT-signed requests). The balance data is sensitive and must be fetched server-side through an API route — never directly from a React component.

Bolt.new Prompt

Build a Coinbase portfolio tracker. Create a Next.js API route at /api/crypto/portfolio that authenticates with Coinbase Advanced Trade API using COINBASE_API_KEY_NAME and COINBASE_PRIVATE_KEY from process.env. Fetch account balances for all cryptocurrency holdings. Calculate total portfolio value in USD using current prices. Display each holding with coin name, quantity, current price, and USD value. Sort by value descending. Note that API key credentials must be stored server-side only.

Copy this prompt to try it in Bolt.new

Troubleshooting

coinbase-commerce-node import fails with 'Cannot find module' or TypeScript type errors

Cause: The package installed correctly but lacks TypeScript type definitions. The @ts-ignore comment in the example suppresses the type error.

Solution: Add // @ts-ignore above the import, or install a community types package. Alternatively, use direct fetch() calls to the Commerce REST API instead of the SDK to avoid the type issue entirely.

typescript
1// Alternative: use fetch directly instead of the SDK:
2const response = await fetch('https://api.commerce.coinbase.com/charges', {
3 method: 'POST',
4 headers: {
5 'X-CC-Api-Key': process.env.COINBASE_COMMERCE_API_KEY || '',
6 'X-CC-Version': '2018-03-22',
7 'Content-Type': 'application/json',
8 },
9 body: JSON.stringify(chargeData),
10});

Commerce webhook signature verification fails — all webhooks return 401

Cause: The raw request body is being parsed as JSON before signature verification, which changes the exact byte sequence and invalidates the HMAC signature.

Solution: Use request.text() (not request.json()) to read the raw body before verification. Only parse it as JSON after verifying the signature. The signature is computed over the exact raw bytes Coinbase sent.

typescript
1// CORRECT — read raw text first, then parse JSON:
2export async function POST(request: Request) {
3 const rawBody = await request.text(); // Must be text, not json
4 // Verify signature using rawBody string
5 const event = JSON.parse(rawBody); // Parse AFTER verification
6}

Commerce webhooks are not arriving — payments succeed in Coinbase but the webhook endpoint logs nothing

Cause: The webhook URL is pointing to Bolt's WebContainer preview URL, which is not publicly accessible. Coinbase cannot reach browser-based runtimes.

Solution: Deploy your app to Netlify or Bolt Cloud and update the webhook URL in Coinbase Commerce Settings > Notifications to use your deployed domain. The WebContainer preview URL (ending in .webcontainer-api.io) is only accessible within your browser session.

Advanced Trade API price requests return 403 or 'Unauthorized' for public endpoints

Cause: A stale or malformed Authorization header is being sent with the public endpoint request. Public endpoints do not require authentication and reject some malformed auth headers.

Solution: Remove any Authorization headers from public endpoint requests. The public Advanced Trade API endpoints (GET /api/v3/brokerage/market/products) do not need authentication and should be called with only the Content-Type header.

typescript
1// Public endpoint — no authorization header needed:
2const res = await fetch(
3 `https://api.coinbase.com/api/v3/brokerage/market/products/${productId}`,
4 { headers: { 'Content-Type': 'application/json' } } // No Authorization header
5);

Best practices

  • Never create Commerce charges speculatively — only create a charge when the user explicitly initiates checkout, since each charge occupies a unique blockchain address and has a 60-minute expiry.
  • Store COINBASE_COMMERCE_API_KEY and Advanced Trade private keys as server-side environment variables without any NEXT_PUBLIC_ prefix to ensure they are never bundled into client JavaScript.
  • Implement idempotency in your webhook handler by storing processed charge IDs and ignoring duplicate events — Coinbase may retry webhook delivery multiple times if your endpoint does not respond quickly enough.
  • Handle the charge:delayed event specifically — this represents a valid payment made after the charge expired and requires manual review rather than automatic fulfillment.
  • Cache public price data for at least 15 seconds to stay within Coinbase's rate limits and reduce latency for users loading price widgets simultaneously.
  • Display crypto amounts with appropriate precision — Bitcoin prices are typically shown with 2 decimal places for USD values, but small-cap coins may need 4-6 decimal places.
  • Always show the USD equivalent prominently alongside crypto prices in payment flows — most customers think in fiat currency and the crypto amount alone may cause confusion or trust issues.

Alternatives

Frequently asked questions

Can I test Coinbase Commerce payments in Bolt's preview without deploying?

You can create charges and get the hosted checkout URL in the Bolt preview — clicking the URL opens Coinbase's hosted payment page and you can simulate a payment there. However, the webhook confirming payment success cannot reach the WebContainer preview since it cannot accept incoming HTTP connections. Full end-to-end payment testing (create charge → customer pays → webhook confirms → app updates) requires deployment to Netlify or Bolt Cloud.

Does Bolt.new have a native Coinbase integration?

No — Bolt.new's native Stripe integration is for fiat payments only. Coinbase Commerce and Coinbase Advanced Trade API require manual setup using Next.js API routes. Bolt's AI assistant generates the full integration from a prompt, so setup is fast even without a native connector.

Are Coinbase public price API endpoints free to use?

Yes — Coinbase Advanced Trade's public market data endpoints (product prices, 24h stats, order books) are free and require no API key or account. They have rate limits (typically a few hundred requests per minute) which are more than sufficient for a dashboard polling every 30 seconds. Only authenticated endpoints for account data, trading, and portfolio access require an API key.

What cryptocurrencies does Coinbase Commerce accept?

Coinbase Commerce supports Bitcoin (BTC), Ethereum (ETH), Litecoin (LTC), Bitcoin Cash (BCH), USD Coin (USDC), DAI, and several other ERC-20 tokens. The list changes as Coinbase adds support for new currencies. Commerce displays all supported options to the customer on the checkout page, so you do not need to specify which coins to accept — customers choose their preferred currency.

How long does it take for a Coinbase Commerce charge:confirmed webhook to fire?

Confirmation time depends on the blockchain and network congestion. Bitcoin typically requires 6 confirmations (approximately 60 minutes), though Commerce may confirm faster for smaller amounts. Ethereum is faster, typically 35 confirmations taking 5-10 minutes. USDC and other stablecoins follow Ethereum's timing. Build your UX to expect a delay between payment submission and confirmation — show the customer a 'processing' state while they wait.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.