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

How to Integrate Bolt.new with Shift4Shop

Connect Bolt.new to Shift4Shop (formerly 3dcart) using its REST API with three credentials: your store's SecureURL, a Public Token, and a Private Key. All API calls must go through a Next.js API route to keep the private key server-side. Build custom storefronts, order dashboards, or product management UIs on top of Shift4Shop's hosted catalog. Outbound REST calls work in Bolt's WebContainer during development.

What you'll learn

  • How to generate API credentials from the Shift4Shop admin panel and authenticate REST requests
  • How to fetch and display product catalogs, categories, and inventory from the Shift4Shop API
  • How to build an order management dashboard that reads orders and filters by status
  • How to create a custom headless storefront experience that uses Shift4Shop as the backend
  • How to configure Shift4Shop webhooks for real-time order notifications after deploying
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate17 min read25 minutesE-commerceApril 2026RapidDev Engineering Team
TL;DR

Connect Bolt.new to Shift4Shop (formerly 3dcart) using its REST API with three credentials: your store's SecureURL, a Public Token, and a Private Key. All API calls must go through a Next.js API route to keep the private key server-side. Build custom storefronts, order dashboards, or product management UIs on top of Shift4Shop's hosted catalog. Outbound REST calls work in Bolt's WebContainer during development.

Build a Custom Shift4Shop Storefront or Admin Dashboard with Bolt.new

Shift4Shop stands out in the e-commerce platform market for a unique reason: it offers a completely free plan with no monthly fees, no transaction fees, and no limits on products or bandwidth — the only condition is using Shift4 Payments as your payment processor. This makes it an attractive backend for builders who want a fully hosted e-commerce engine without the $29/month Shopify Basic subscription.

The Shift4Shop REST API gives you programmatic access to everything in your store: products, categories, orders, customers, inventory, shipping options, and coupons. This enables two powerful use cases with Bolt.new. First, you can build a completely custom storefront — your own React UI pulling product and catalog data from Shift4Shop, with Shift4Shop handling the cart, checkout, and payment processing in the background. Second, you can build internal admin dashboards for order fulfillment, inventory management, or sales reporting that your team uses alongside or instead of the default Shift4Shop admin interface.

Authentication uses three values: the store's SecureURL (the base URL for API calls), a Public Token (can be used for read-only catalog calls in some contexts), and a Private Key (required for all order and customer data). The Private Key must never leave your server — store it in .env and access it only from Next.js API routes. During Bolt.new development, all outbound calls to Shift4Shop work in the WebContainer. If you need Shift4Shop to push order or inventory events to your app via webhooks, you must deploy to Netlify or Vercel first and register a public URL.

Integration method

Bolt Chat + API Route

Shift4Shop's REST API uses three-credential authentication: a SecureURL (your store's API endpoint), a Public Token (safe to use in some contexts), and a Private Key (server-side only). All requests to the Shift4Shop API must be made from a Next.js API route where the Private Key is kept in server-side environment variables. Bolt.new's WebContainer supports outbound HTTP calls to the Shift4Shop API during development. Webhook events from Shift4Shop require a deployed URL on Netlify or Vercel since they send incoming POST requests.

Prerequisites

  • A Shift4Shop store — sign up free at shift4shop.com (free plan available with Shift4 Payments)
  • API credentials from Shift4Shop admin: Settings → API → Generate API Access Token (gives you SecureURL, Public Token, and Private Key)
  • A Bolt.new account with a new Next.js project open
  • Products already added to your Shift4Shop store to test catalog and inventory API calls
  • A Netlify account for deployment if you need Shift4Shop order notification webhooks

Step-by-step guide

1

Generate Shift4Shop API credentials and set up authentication

Shift4Shop uses a three-part authentication system that you include as HTTP request headers on every API call. Understanding each credential's purpose helps you use them correctly and securely. To generate credentials: log into your Shift4Shop admin panel, go to Settings (gear icon) → API → REST API. If you haven't enabled the REST API, toggle it on. Click Generate to create a new API access token. Shift4Shop shows you three values: 1. SecureURL — This is the base URL for all your API calls. It looks like `https://api.shift4shop.com/v3/{your-store-id}`. Every API request goes to this URL plus the endpoint path (e.g., `/Products`, `/Orders`). 2. PublicToken — A token that can be used for read-only catalog operations. Some integrations use this in client-side code for public data like product listings. However, for consistency and security, this guide uses it server-side only in API routes. 3. PrivateKey — This is the sensitive credential that authenticates write operations and access to order/customer data. It must never appear in client-side code, NEXT_PUBLIC_ environment variables, or be committed to Git. All three headers are sent together on every request: `SecureURL`, `PublicToken`, and `PrivateKey` as HTTP headers. The Shift4Shop API is RESTful with standard HTTP verbs (GET for reads, POST for creates, PUT for updates, DELETE for deletions) and returns JSON. Add all three values to your .env file in Bolt. The Shift4Shop REST API accepts HTTPS requests, and these outbound calls work correctly in Bolt's WebContainer during development.

Bolt.new Prompt

Set up Shift4Shop API authentication in my Next.js project. Create a .env file with SHIFT4SHOP_SECURE_URL=https://api.shift4shop.com/v3/your-store-id, SHIFT4SHOP_PUBLIC_TOKEN=your-public-token, and SHIFT4SHOP_PRIVATE_KEY=your-private-key. Create a lib/shift4shop.ts helper file that exports a shift4shopFetch function. This function accepts an endpoint string (like '/Products') and optional init RequestInit. It reads the three env vars, sends them as SecureURL, PublicToken, and PrivateKey headers, appends Content-Type application/json, and fetches from SHIFT4SHOP_SECURE_URL + endpoint. Throw a descriptive error if any env var is missing. Return the parsed JSON.

Paste this in Bolt.new chat

lib/shift4shop.ts
1// lib/shift4shop.ts
2const getCredentials = () => {
3 const secureUrl = process.env.SHIFT4SHOP_SECURE_URL;
4 const publicToken = process.env.SHIFT4SHOP_PUBLIC_TOKEN;
5 const privateKey = process.env.SHIFT4SHOP_PRIVATE_KEY;
6
7 if (!secureUrl || !publicToken || !privateKey) {
8 throw new Error(
9 'Missing Shift4Shop credentials. Set SHIFT4SHOP_SECURE_URL, ' +
10 'SHIFT4SHOP_PUBLIC_TOKEN, and SHIFT4SHOP_PRIVATE_KEY in .env'
11 );
12 }
13 return { secureUrl, publicToken, privateKey };
14};
15
16export async function shift4shopFetch<T = unknown>(
17 endpoint: string,
18 init: RequestInit = {}
19): Promise<T> {
20 const { secureUrl, publicToken, privateKey } = getCredentials();
21 const url = `${secureUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
22
23 const response = await fetch(url, {
24 ...init,
25 headers: {
26 SecureURL: secureUrl,
27 PublicToken: publicToken,
28 PrivateKey: privateKey,
29 'Content-Type': 'application/json',
30 Accept: 'application/json',
31 ...init.headers,
32 },
33 });
34
35 if (!response.ok) {
36 const errorText = await response.text();
37 throw new Error(`Shift4Shop API ${response.status}: ${errorText}`);
38 }
39
40 return response.json() as Promise<T>;
41}

Pro tip: The Shift4Shop REST API documentation is at developers.shift4shop.com. Each resource (Products, Orders, Customers) has its own endpoint. The SecureURL already includes your store identifier, so endpoint paths are just the resource names — for example, GET /Products returns your full product catalog.

Expected result: A configured Shift4Shop API helper in lib/shift4shop.ts with all three credentials stored in .env, ready to use in API routes.

2

Fetch products and build a catalog API route

The Shift4Shop Products endpoint (`GET /Products`) returns your store's full product catalog with rich data including name, description, SKU, price, sale price, stock levels, categories, images, and custom fields. This is the foundation for any custom storefront or catalog integration. The Products endpoint supports several useful query parameters for pagination and filtering. `countonly=1` returns just the count of matching products — useful for determining how many pages to show. `offset` and `limit` control pagination (max 200 per request). `categoryid` filters by category. `hide=false` returns only active/visible products. For custom storefronts, you typically want `hide=false` to match what your live store shows. Product images are returned in the `Images` array — the first image is typically the primary product image. Each image object includes `Url` (the full CDN URL) and `AltText`. Shift4Shop hosts these images on their CDN, so you can use the URLs directly in your React components without any additional asset handling. Inventory data is included in the product response as `Stock`, `StockAlert` (the low stock threshold), and `InventoryControl` (whether stock tracking is enabled for this product). This makes it easy to build inventory-aware UIs — showing 'Out of Stock' badges, filtering to in-stock products only, or building the inventory alert dashboard described in the use cases. For large catalogs, implement pagination in your API route using `offset` and `limit` parameters. A catalog with 500+ products should never be fetched in one call — load the first page immediately and implement infinite scroll or 'load more' pagination in your React component.

Bolt.new Prompt

Create a products API route at app/api/shift4shop/products/route.ts. Accept GET requests with optional query params: limit (default 20, max 200), offset (default 0), categoryId (optional), inStockOnly (optional boolean). Use shift4shopFetch from lib/shift4shop.ts to GET /Products with these params. Return the products array with id, name, sku, price, salePrice, stock, thumbnail (first image URL), and isInStock. Also create a React ProductGrid component at components/ProductGrid.tsx that fetches from this route, displays products in a responsive 3-column grid with product name, price (crossed out if there's a sale price), stock badge, and image.

Paste this in Bolt.new chat

app/api/shift4shop/products/route.ts
1// app/api/shift4shop/products/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { shift4shopFetch } from '@/lib/shift4shop';
4
5interface Shift4ShopProduct {
6 CatalogID: number;
7 SKU: string;
8 Name: string;
9 Price: number;
10 SalePrice: number;
11 Stock: number;
12 Hide: boolean;
13 Images: Array<{ Url: string; AltText: string }>;
14 CategoryID: number;
15}
16
17export async function GET(request: NextRequest) {
18 const { searchParams } = new URL(request.url);
19 const limit = Math.min(Number(searchParams.get('limit') ?? 20), 200);
20 const offset = Number(searchParams.get('offset') ?? 0);
21 const categoryId = searchParams.get('categoryId');
22 const inStockOnly = searchParams.get('inStockOnly') === 'true';
23
24 const params = new URLSearchParams({
25 limit: limit.toString(),
26 offset: offset.toString(),
27 hide: 'false',
28 });
29 if (categoryId) params.set('categoryid', categoryId);
30
31 const products = await shift4shopFetch<Shift4ShopProduct[]>(
32 `/Products?${params.toString()}`
33 );
34
35 const normalized = products
36 .filter(p => !inStockOnly || p.Stock > 0)
37 .map(p => ({
38 id: p.CatalogID,
39 sku: p.SKU,
40 name: p.Name,
41 price: p.Price,
42 salePrice: p.SalePrice > 0 && p.SalePrice < p.Price ? p.SalePrice : null,
43 stock: p.Stock,
44 isInStock: p.Stock > 0,
45 thumbnail: p.Images?.[0]?.Url ?? null,
46 }));
47
48 return NextResponse.json({ products: normalized, offset, limit });
49}

Pro tip: Shift4Shop product images are hosted on Shift4Shop's CDN. You can use these URLs directly in Next.js Image components — add 'cdn.3dcart.com' to your next.config.js images.domains array to avoid the 'unconfigured hostname' error.

Expected result: A products API route that returns normalized product data from Shift4Shop, and a React component displaying the catalog in a responsive grid.

3

Build an order management API route and dashboard

The Shift4Shop Orders endpoint (`GET /Orders`) returns all orders with full details including customer information, line items, shipping method, order status, and payment status. This is the data your fulfillment team needs to process and ship orders. Shift4Shop uses numeric status codes for order status. The key ones are: 1 (New), 2 (Processing), 3 (Awaiting Fulfillment), 4 (Shipped), 5 (Cancelled), 6 (Declined), 7 (Awaiting Payment), 8 (Backordered), 9 (Awaiting Shipment), 12 (Refunded). For a fulfillment dashboard, you typically filter to status 1 (New), 2 (Processing), and 9 (Awaiting Shipment). Orders include the `OrderItems` array with each line item's product name, SKU, quantity, unit price, and the order subtotal, shipping cost, tax amount, and total. The `ShipmentList` array shows any shipments created for the order with tracking numbers. Customer data is embedded in the order: `BillingFirstName`, `BillingLastName`, `BillingEmail`, and the `ShipFirstName`, `ShipLastName`, `ShipAddress` fields for the delivery address. All the information your team needs to print a packing slip or verify an address is in one API call. For the dashboard, a well-organized order table dramatically speeds up fulfillment workflows. Show order number, customer name, destination city/state, item count, order total, and status badge. Make the order number clickable to expand a drawer showing full line items and customer details. Add a status filter dropdown so the team can focus on orders needing attention.

Bolt.new Prompt

Create an orders API route at app/api/shift4shop/orders/route.ts. Accept GET with optional query params: status (numeric code, default empty = all), limit (default 50), offset (default 0). Use shift4shopFetch to GET /Orders with these params. Return normalized orders with id, orderDate, customerName, customerEmail, status, statusLabel, itemCount, total, and shippingAddress (city, state, country). Create a status label map for Shift4Shop status codes (1=New, 2=Processing, 4=Shipped, etc.). Build a React OrdersDashboard component with a status filter dropdown and a sortable table.

Paste this in Bolt.new chat

app/api/shift4shop/orders/route.ts
1// app/api/shift4shop/orders/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { shift4shopFetch } from '@/lib/shift4shop';
4
5const STATUS_LABELS: Record<number, string> = {
6 1: 'New',
7 2: 'Processing',
8 3: 'Awaiting Fulfillment',
9 4: 'Shipped',
10 5: 'Cancelled',
11 6: 'Declined',
12 7: 'Awaiting Payment',
13 8: 'Backordered',
14 9: 'Awaiting Shipment',
15 12: 'Refunded',
16};
17
18interface Shift4ShopOrder {
19 InvoiceNumber: number;
20 InvoiceDate: string;
21 BillingFirstName: string;
22 BillingLastName: string;
23 BillingEmail: string;
24 OrderStatus: number;
25 OrderItems: unknown[];
26 OrderAmount: number;
27 ShipCity: string;
28 ShipState: string;
29 ShipCountry: string;
30}
31
32export async function GET(request: NextRequest) {
33 const { searchParams } = new URL(request.url);
34 const status = searchParams.get('status');
35 const limit = searchParams.get('limit') ?? '50';
36 const offset = searchParams.get('offset') ?? '0';
37
38 const params = new URLSearchParams({ limit, offset });
39 if (status) params.set('StatusID', status);
40
41 const orders = await shift4shopFetch<Shift4ShopOrder[]>(
42 `/Orders?${params.toString()}`
43 );
44
45 const normalized = orders.map(o => ({
46 id: o.InvoiceNumber,
47 orderDate: o.InvoiceDate,
48 customerName: `${o.BillingFirstName} ${o.BillingLastName}`.trim(),
49 customerEmail: o.BillingEmail,
50 status: o.OrderStatus,
51 statusLabel: STATUS_LABELS[o.OrderStatus] ?? `Status ${o.OrderStatus}`,
52 itemCount: o.OrderItems?.length ?? 0,
53 total: o.OrderAmount,
54 shippingAddress: {
55 city: o.ShipCity,
56 state: o.ShipState,
57 country: o.ShipCountry,
58 },
59 }));
60
61 return NextResponse.json({ orders: normalized });
62}

Pro tip: Shift4Shop's order status codes are numeric and not immediately obvious. Keep the STATUS_LABELS map in a shared constants file so it is consistent across your dashboard components and any webhook handlers that process status change events.

Expected result: An orders API route returning normalized Shift4Shop order data with readable status labels, and a dashboard component for filtering and viewing orders.

4

Deploy to Netlify and configure Shift4Shop webhooks

Outbound Shift4Shop API calls work flawlessly during Bolt.new development in the WebContainer — fetching products, orders, and inventory all function correctly in the preview environment. The only functionality that requires deployment is Shift4Shop's real-time notification system, which uses webhooks to push order and shipment events to your app. Shift4Shop offers webhook notifications (called 'Callbacks' in their interface) for events including new orders, order status changes, and inventory updates. These are POST requests sent from Shift4Shop servers to your endpoint URL. Since Bolt.new's WebContainer has no persistent public URL and cannot receive incoming HTTP connections, these notifications cannot reach your app during development. To deploy and configure webhooks: click Deploy in Bolt.new and connect your Netlify account. After deployment succeeds, go to your Netlify dashboard → Site Configuration → Environment Variables and add all three Shift4Shop credentials: `SHIFT4SHOP_SECURE_URL`, `SHIFT4SHOP_PUBLIC_TOKEN`, and `SHIFT4SHOP_PRIVATE_KEY`. Trigger a redeploy to apply the variables. For Shift4Shop webhooks: log into your Shift4Shop admin, go to Settings → API → Webhooks (or Callbacks depending on your version). Add a new webhook pointing to `https://your-app.netlify.app/api/shift4shop/webhook` for Order events. Shift4Shop sends a POST with the order number when triggered — your handler then calls back to the Shift4Shop API using the order number to fetch full details. This two-step pattern (notification → fetch) is common in e-commerce platform webhooks. A practical use case for the webhook: send an order confirmation email via SendGrid when Shift4Shop posts a new order notification. The webhook receives the order ID, your handler fetches the full order details from Shift4Shop, and then sends a branded email to the customer.

Bolt.new Prompt

Create a Shift4Shop webhook handler at app/api/shift4shop/webhook/route.ts. Accept POST requests. Parse the body which contains orderId or InvoiceNumber. Use shift4shopFetch to GET /Orders/{orderId} to fetch the full order details. Log the order number, customer name, and total. Always return 200. Add a clear comment that this webhook handler requires a deployed public URL — it cannot be triggered against Bolt.new's WebContainer preview. Also create netlify.toml with Next.js build configuration.

Paste this in Bolt.new chat

app/api/shift4shop/webhook/route.ts
1// app/api/shift4shop/webhook/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { shift4shopFetch } from '@/lib/shift4shop';
4
5// IMPORTANT: Shift4Shop webhooks require a publicly deployed URL.
6// During Bolt.new WebContainer development, incoming webhook callbacks
7// cannot be received. Deploy to Netlify first, then configure your
8// webhook URL in Shift4Shop Admin → Settings → API → Webhooks.
9export async function POST(request: NextRequest) {
10 try {
11 const body = await request.json();
12 const orderId = body.InvoiceNumber ?? body.orderId;
13
14 if (orderId) {
15 // Fetch full order details using the order ID from the notification
16 const orders = await shift4shopFetch<unknown[]>(
17 `/Orders?InvoiceNumber=${orderId}`
18 );
19 const order = Array.isArray(orders) ? orders[0] : orders;
20
21 if (order) {
22 const o = order as Record<string, unknown>;
23 console.log(
24 `New Shift4Shop order #${orderId}: ` +
25 `${o.BillingFirstName} ${o.BillingLastName} — ` +
26 `$${o.OrderAmount}`
27 );
28 // TODO: Send order confirmation email, update internal database, etc.
29 }
30 }
31 } catch (error) {
32 // Log but don't expose — always return 200 to acknowledge receipt
33 console.error('Shift4Shop webhook error:', error);
34 }
35
36 // Always return 200 to prevent Shift4Shop from retrying
37 return NextResponse.json({ received: true });
38}

Pro tip: Shift4Shop refers to their webhook system as 'Callbacks' in some documentation versions and 'Webhooks' in others — both refer to the same outbound HTTP notification feature. Look for both terms when navigating the admin interface.

Expected result: A deployed Netlify app with a webhook handler ready to receive Shift4Shop order notifications, enabling real-time order processing workflows.

Common use cases

Custom Product Catalog Page

Build a visually rich product catalog using your own React components and Tailwind CSS, pulling live product data from Shift4Shop. Display products with custom filtering, sorting, and layout that matches your brand — not the default Shift4Shop theme.

Bolt.new Prompt

Create a product catalog page for my Shift4Shop store. Build an API route at app/api/shift4shop/products/route.ts that fetches all products from the Shift4Shop REST API using SecureURL from SHIFT4SHOP_SECURE_URL, PublicToken from SHIFT4SHOP_PUBLIC_TOKEN, and PrivateKey from SHIFT4SHOP_PRIVATE_KEY as request headers. Return an array of products with id, name, price, thumbnail, and stock. Create a React ProductCatalog component that fetches from this route and displays products in a responsive grid with search and category filter.

Copy this prompt to try it in Bolt.new

Order Management Dashboard

Create an internal order management view that shows recent orders, their status, customer details, and line items. Allow your fulfillment team to filter by status, search by order number, and view shipping details without logging into the Shift4Shop admin panel.

Bolt.new Prompt

Build an order management dashboard. Create an API route at app/api/shift4shop/orders/route.ts that fetches orders from Shift4Shop using the three auth headers (SecureURL, PublicToken, PrivateKey from process.env). Accept query params for status filter (new, processing, shipped, cancelled) and limit (default 50). Return order ID, customer name, order date, status, total, and item count. Build a React Orders component with a filterable table, showing each order's key details and a status badge with appropriate color coding.

Copy this prompt to try it in Bolt.new

Low Stock Inventory Alert Dashboard

Build a dashboard that surfaces products with low inventory levels so your team can reorder before stockouts. Poll Shift4Shop for products with stock below a configurable threshold and display them prioritized by urgency.

Bolt.new Prompt

Create an inventory management page that shows low-stock products. Build an API route at app/api/shift4shop/inventory/route.ts that fetches all products from Shift4Shop and filters to those with stock below a threshold (default 10 units). Sort by stock ascending. Return product name, SKU, current stock, and price. Build a React InventoryAlerts component that shows these products in a table with stock count color-coded (red for 0-3, orange for 4-9), and a header showing the total count of low-stock items.

Copy this prompt to try it in Bolt.new

Troubleshooting

API returns 401 Unauthorized even with correct credentials in headers

Cause: Shift4Shop requires all three headers (SecureURL, PublicToken, PrivateKey) to be present on every request, not just the PrivateKey. A common mistake is sending only one or two headers. Another cause is using the REST API URL as the base URL but omitting it from the SecureURL header — both the URL and the header must be present.

Solution: Verify that all three headers are included in every request: SecureURL (the full API base URL), PublicToken, and PrivateKey. Check your lib/shift4shop.ts helper to confirm all three are being set. Also verify the header names are exactly as Shift4Shop expects — they are case-sensitive. Log the request headers in development to confirm they are being sent.

Products endpoint returns an empty array even though products exist in the store

Cause: Shift4Shop hides inactive products by default in some API configurations. If products are set to 'Hide' in the admin panel, or if the API call is not filtering correctly, you may receive an empty result. The free plan also requires Shift4 Payments to be active — stores that haven't completed payment setup may have API access restrictions.

Solution: Add hide=false to your query parameters to include all active products. Check in the Shift4Shop admin that your products are not set to 'Hidden'. If you are on the free plan, verify your Shift4 Payments account is fully set up and connected — incomplete payment setup can restrict API access.

typescript
1// Add hide=false to ensure active products are returned
2const params = new URLSearchParams({ limit: '20', offset: '0', hide: 'false' });
3const products = await shift4shopFetch(`/Products?${params.toString()}`);

Shift4Shop webhook callbacks are not arriving in Bolt.new

Cause: Bolt.new's WebContainer does not have a persistent public URL that external services can reach. Shift4Shop's callback/webhook system sends POST requests to your registered URL, requiring a publicly accessible server. The Bolt.new preview URL is not a valid callback target.

Solution: Deploy your app to Netlify, then register the deployed URL in Shift4Shop admin Settings → API → Webhooks/Callbacks. Use your Netlify domain (e.g., https://your-app.netlify.app/api/shift4shop/webhook). This is a fundamental limitation of WebContainers — incoming HTTP connections always require a deployed environment.

Images from Shift4Shop products show 'unconfigured host' error in Next.js Image component

Cause: Next.js requires all external image domains to be explicitly listed in next.config.js before they can be used in the next/image component. Shift4Shop hosts images on 3dcart.com CDN domains.

Solution: Add the Shift4Shop CDN domain to your next.config.js images configuration. The primary CDN domain is cdn.3dcart.com — add it to the remotePatterns or domains array.

typescript
1// next.config.js
2module.exports = {
3 images: {
4 remotePatterns: [
5 { protocol: 'https', hostname: 'cdn.3dcart.com' },
6 { protocol: 'https', hostname: '*.3dcart.com' },
7 ],
8 },
9};

Best practices

  • Store all three Shift4Shop credentials (SecureURL, PublicToken, PrivateKey) as server-side environment variables — never expose any of them in NEXT_PUBLIC_ variables or client-side code
  • Create a centralized lib/shift4shop.ts helper that handles authentication headers for all API calls, rather than repeating the auth logic in every API route
  • Implement pagination for large catalogs — the Products endpoint allows up to 200 items per request, but stores with thousands of products should use offset-based pagination
  • Add response caching for product catalog data since product listings change infrequently — cache for 60-300 seconds to reduce API calls and improve page load times
  • Use Shift4Shop's status code constants in a shared mapping object rather than hardcoding numeric status values directly in components
  • Always return HTTP 200 from webhook handlers even if processing fails — Shift4Shop retries failed callbacks which can cause duplicate order processing
  • Test your API routes against the Shift4Shop API from Bolt's WebContainer preview before deploying — all outbound calls work in development and catching errors early saves time
  • For headless storefront use cases, use the Public Token for read-only product/category queries and reserve the Private Key usage for order and customer data API routes

Alternatives

Frequently asked questions

Is Shift4Shop really free?

Yes, Shift4Shop's Free plan offers unlimited products, orders, bandwidth, and storage with no monthly subscription fees. The condition is using Shift4 Payments as your payment processor. Shift4 charges a payment processing fee (similar to Stripe or Square) but eliminates the platform subscription cost. This makes it among the most cost-effective hosted e-commerce platforms for high-volume sellers.

Can I use Shift4Shop's API from Bolt.new during development without deploying?

Yes. All outbound API calls to Shift4Shop's REST API work in Bolt.new's WebContainer during development. You can fetch products, orders, inventory, and customer data from the preview environment. The only feature requiring deployment is Shift4Shop's webhook/callback system, which sends incoming POST requests that WebContainers cannot receive.

What's the difference between Shift4Shop's Public Token and Private Key?

The Public Token is designed for read-only operations on public catalog data — some implementations use it client-side to fetch product listings. The Private Key provides full API access including order management, customer data, and write operations. For security, this guide treats both as server-side only credentials and never exposes either in client-side code or NEXT_PUBLIC_ environment variables.

Can Bolt.new handle Shift4Shop's webhook callbacks?

Yes, after deployment. Write your webhook handler in Bolt.new, deploy to Netlify, and register the Netlify URL in Shift4Shop's admin panel (Settings → API → Webhooks). The WebContainer cannot receive incoming HTTP connections during development — this is a fundamental limitation of the browser-based runtime, not a Bolt.new-specific issue.

How do I handle Shift4Shop's pagination for large product catalogs?

Use the offset and limit query parameters on the /Products endpoint. Limit is capped at 200 per request. First call /Products?countonly=1 to get the total product count, then calculate how many pages you need. Implement either traditional pagination (page number controls) or infinite scroll in your React component, loading additional pages as the user scrolls. For catalogs under 200 products, a single call with limit=200 fetches everything.

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.