# Ecwid

- Tool: Bubble
- Difficulty: Beginner
- Time required: 30 minutes (widget) / 2 hours (REST API)
- Last updated: July 2026

## TL;DR

Connect Bubble to Ecwid two ways: embed the Ecwid JS widget in an HTML element for instant embedded checkout (no API calls, works on any Bubble plan), or set up the API Connector with a Bearer token and store ID for full programmatic access to products, orders, and customers. The REST API requires a paid Ecwid plan (Venture or above) — Free plan users can only use the widget embed.

## Widget Embed or REST API — Choose the Right Ecwid Integration for Bubble

Most Bubble builders don't know that Ecwid offers two completely different integration modes, and choosing the wrong one wastes hours. If your goal is to add a working online store to a Bubble page quickly — with products, cart, and checkout all handled by Ecwid — the JS widget embed does it in two minutes with zero API configuration. You paste a snippet into a Bubble HTML element, and Ecwid renders a complete embeddable storefront. Cart, checkout, payment, and order confirmation are all managed by Ecwid's system. You do not need an API key, and it works on Bubble's Free plan. This is the right choice for merchants who are already selling on Ecwid and want to surface their store inside a Bubble page without building custom commerce logic. If you need to build something custom — a product admin panel, an order management dashboard, a custom storefront with your own design system, or data syncing between Ecwid and other Bubble workflows — you need the REST API approach. The Ecwid REST API uses Bearer token authentication with your numeric store ID embedded in the base URL. The API provides full access to products, orders, customers, and discount codes. However, the REST API is only available on Ecwid's Venture plan ($19/month) or higher — users on the Free plan who try to use the API Connector will receive 403 Forbidden errors. This tutorial walks through both paths so you can get the right one set up based on what you are building.

## Before you start

- An Ecwid account — a Free account is sufficient for the JS widget embed only
- An Ecwid Venture plan ($19/month) or higher if you need REST API access — the Free plan blocks API calls with 403 errors
- Your Ecwid Store ID — the numeric value visible in your Ecwid Control Panel URL (e.g., store12345678 means your store ID is 12345678)
- Your Ecwid API access token — generated from Control Panel → Settings → API (only available on Venture plan or above)
- The API Connector plugin installed in your Bubble app (free, published by Bubble) — only needed for the REST API path, not the widget embed

## Step-by-step guide

### 1. Option A — Embed the Ecwid Widget (Any Plan, 2 Minutes)

The quickest way to add Ecwid to Bubble is the JavaScript widget embed. This approach requires no API key and works on any Bubble plan including Free. Go to your Ecwid Control Panel and find your Store ID — it is the numeric value in the admin URL after 'store' (e.g., if the URL is https://my.ecwid.com/store/12345678 then your Store ID is 12345678). In your Bubble app editor, open the page where you want the store to appear. In the Elements panel, drag an HTML element onto the page. Resize it to fill the area where the store should display. Click on the HTML element to open its properties and find the 'HTML' field. Paste the following two-line embed script, replacing 12345678 with your actual numeric Store ID. The first line loads the Ecwid JavaScript and the second line creates the container div. After saving and previewing the page, the full Ecwid storefront — product listings, categories, cart, and checkout — will appear inside the HTML element. Ecwid handles all cart state, payment processing (via your configured payment gateway), and order recording automatically. You do not need any Bubble workflows, API calls, or data types for this approach — Ecwid manages everything within the widget. To customize the store's appearance, use Ecwid's Design → Theme editor in the Control Panel.

```
<!-- Ecwid JS Widget Embed — paste into Bubble HTML element -->
<!-- Replace 12345678 with YOUR numeric Ecwid Store ID -->

<script
  data-cfasync="false"
  type="text/javascript"
  src="https://app.ecwid.com/script.js?12345678"
  charset="utf-8">
</script>
<div id="my-store-12345678"></div>

<!-- The div ID must match: my-store-{YOUR_STORE_ID} -->
<!-- After embedding: Ecwid handles cart, checkout, payments, and orders -->
<!-- No API key needed. Works on Bubble Free plan. -->
```

**Expected result:** The Ecwid storefront appears inside the HTML element on your Bubble page. Products are displayed in Ecwid's default theme, the cart works, and customers can complete checkout. Orders appear in your Ecwid Control Panel automatically.

### 2. Option B — Set Up the REST API with Bearer Token (Venture Plan Required)

For custom product displays, order management, or any workflow that needs to read or write Ecwid data from Bubble, use the REST API path. First, confirm your Ecwid plan is Venture or above — the API is blocked on the Free plan. In Ecwid Control Panel, go to Settings → API. If you see API credentials there, your plan includes API access. If you see an upgrade prompt, you need to upgrade before proceeding. Copy your Access Token from the API settings page. Also confirm your Store ID (the numeric value in your admin URL). Now go to your Bubble app editor. Open Plugins tab → Add plugins → search 'API Connector' (published by Bubble) and install it. Click on the API Connector and click 'Add another API'. Name the group 'Ecwid API'. Set the root URL to https://app.ecwid.com/api/v3/YOUR_STORE_ID — replace YOUR_STORE_ID with your actual numeric store ID. Hardcoding the store ID into the base URL means you do not need to pass it as a parameter on every individual call. Add shared headers: Authorization with value 'Bearer YOUR_ACCESS_TOKEN' (check the Private checkbox) and Accept with value application/json. Save the group. Your Bubble app can now make authenticated calls to the Ecwid REST API.

```
// Ecwid REST API Connector Group Configuration
// Store ID is embedded in the base URL — no need to repeat it per call
{
  "groupName": "Ecwid API",
  "rootURL": "https://app.ecwid.com/api/v3/YOUR_STORE_ID",
  "sharedHeaders": [
    {
      "name": "Authorization",
      "value": "Bearer YOUR_ACCESS_TOKEN",
      "private": true
    },
    {
      "name": "Accept",
      "value": "application/json",
      "private": false
    },
    {
      "name": "Content-Type",
      "value": "application/json",
      "private": false
    }
  ]
}

// Replace YOUR_STORE_ID with your numeric Ecwid store ID (e.g., 12345678)
// Replace YOUR_ACCESS_TOKEN with the token from Control Panel → Settings → API
```

**Expected result:** The Ecwid API group appears in the API Connector with your store ID in the base URL and a Private Bearer token header. You are ready to add and initialize API calls for products, orders, and customers.

### 3. Initialize the API Call and Confirm Authentication

Before building any pages, verify your API credentials by initializing a simple call. In the Ecwid API group, click 'Add another call'. Name it 'Get Profile'. Set the method to GET and the path to /profile — this endpoint returns basic store information and is the lightest initialization call available. Click 'Initialize call'. A successful response returns your store name, website URL, country, and store ID. If initialization succeeds, Bubble detects these fields and the call is ready to use. If you receive HTTP 403 Forbidden: your Ecwid plan does not include API access. The Free plan blocks all API calls with a 403. Upgrade to Venture or above and regenerate your access token. If you receive HTTP 401 Unauthorized: the Bearer token is wrong or expired. Go back to Ecwid Control Panel → Settings → API, verify the token value, and update the Authorization header in the API Connector. After the profile call initializes successfully, add the products call: click 'Add another call', name it 'Get Products', method GET, path /products. Add parameters: offset (default 0), limit (default 20, max 100, for initialization use 10). Click Initialize call. Ecwid wraps product list responses in a {total, count, offset, limit, items: [...]} object — after initialization, Bubble will detect fields like 'items first item's name', 'items first item's price', 'total', etc. The data path you use for the Repeating Group is the 'items' array.

```
// Ecwid GET /products response structure
{
  "total": 48,
  "count": 10,
  "offset": 0,
  "limit": 10,
  "items": [
    {
      "id": 66821181,
      "sku": "COFMUG001",
      "name": "Handcrafted Coffee Mug",
      "price": 19.99,
      "compareToPrice": 24.99,
      "quantity": 25,
      "unlimited": false,
      "inStock": true,
      "thumbnailUrl": "https://images.ecwid.com/images/store/12345678/...",
      "imageUrl": "https://images.ecwid.com/images/store/12345678/...",
      "smallThumbnailUrl": "https://images.ecwid.com/images/store/12345678/...",
      "categoryIds": [19563513],
      "description": "<p>A beautifully crafted mug...</p>",
      "weight": 0.4,
      "enabled": true
    }
  ]
}
```

**Expected result:** The profile call initializes successfully showing your store information. The products call initializes and Bubble detects the items array with product fields. You can see 'Get Products's items first item's name', 'items first item's price', and similar field paths ready to use in Repeating Groups.

### 4. Build a Product Catalog Page with Custom Design

Create a new Bubble page named 'Shop'. Add a Repeating Group with 3 columns and 4 rows (or your preferred layout) and set it to a horizontal scroll or a grid layout depending on your design needs. For the data source, choose 'Get data from an external API' → Ecwid API → Get Products. Bubble uses the items array automatically since that is what was detected during initialization. Create a page-level custom state named 'current_offset' (type Number, default 0) for pagination. Wire the offset parameter in the Get Products call to this state, and set limit to a fixed value like 12. Inside the Repeating Group, add an Image element and set its source to 'Current Cell's Get Products's items first item's thumbnailUrl'. Add a Conditional on the Image: when 'Current Cell's Get Products's items first item's thumbnailUrl is empty', change the source to 'Current Cell's Get Products's items first item's imageUrl' as a fallback. Add Text elements for the product name and a formatted price. For the price, Ecwid returns prices as standard decimal numbers (19.99, not smallest-unit integers like some other APIs), so you can display them directly with a currency format. Add Previous and Next pagination buttons: Next button increases current_offset by the limit amount (e.g., +12); Previous button decreases it by the same amount with a condition preventing it going below 0. To show total product count, reference 'Get Products's total' from the API call result. If you want to add a category filter, call GET /categories to fetch your Ecwid categories, display them in a dropdown, and pass the selected categoryId as a parameter to the products call. Note: if you need a RapidDev team to review your Ecwid catalog architecture or help with complex filter logic, visit rapidevelopers.com/contact for a free scoping call.

**Expected result:** The Shop page displays a grid of Ecwid products with images, names, and prices in your Bubble design. The pagination buttons work correctly. Products with no images show the fallback image. The total product count is visible.

### 5. Build Order Management Using the Orders API

Add an order management section for admin use. In the API Connector, add a new call named 'Get Orders' — method GET, path /orders. Add parameters: offset (pagination), limit (results per page, e.g., 20), fulfillmentStatus (to filter by status — use uppercase string values), paymentStatus (optional additional filter). Initialize with offset=0 and limit=5 to get the field schema. Important Ecwid-specific detail for order updates: the path segment for order operations is /orders/{orderNumber} where orderNumber is the human-readable order number (like 1001, 1002), NOT an internal UUID. The GET orders response includes both 'id' (internal, not for paths) and 'orderNumber' (use this for paths). Build an Orders page with a Repeating Group bound to Get Orders. Display customer name, order total, and fulfillmentStatus. Add a dropdown filter for fulfillmentStatus using Ecwid's exact uppercase status values: AWAITING_PROCESSING, PROCESSING, SHIPPED, DELIVERED, WILL_NOT_DELIVER, RETURNED. To update order fulfillment status, add a PUT call to /orders/{orderNumber} with a JSON body containing the new fulfillmentStatus. Run this from a Backend Workflow (paid Bubble plan) with the orderNumber and new status as inputs. After updating, re-fetch the order to confirm the status change and refresh the Repeating Group.

```
// Ecwid order fulfillment status values — use these EXACT uppercase strings
// in GET /orders?fulfillmentStatus= filter AND in PUT /orders/{orderNumber} body
const ECWID_FULFILLMENT_STATUSES = [
  "AWAITING_PROCESSING",
  "PROCESSING",
  "SHIPPED",
  "DELIVERED",
  "WILL_NOT_DELIVER",
  "RETURNED"
];

// PUT /orders/{orderNumber} — update fulfillment status
// Use orderNumber from GET /orders response, NOT the internal 'id' field
{
  "method": "PUT",
  "path": "/orders/<orderNumber dynamic>",
  "body": {
    "fulfillmentStatus": "<newStatus dynamic>"
  }
}

// IMPORTANT: Ecwid GET /orders response contains:
// id: internal numeric ID (do NOT use for API paths)
// orderNumber: human-readable order number — USE THIS for /orders/{orderNumber} paths
```

**Expected result:** The order management page displays Ecwid orders with customer details and fulfillment status. The status dropdown filter correctly shows only orders matching the selected status. Status updates through the Backend Workflow apply successfully and the updated status appears after refreshing.

## Best practices

- Choose the widget embed approach if you need a working Ecwid storefront on a Bubble page quickly and do not need custom design or workflow integration — it takes 2 minutes and requires no API key or paid plan.
- Mark the Ecwid Bearer token as Private in the API Connector — this keeps it server-side in Bubble's infrastructure and prevents it from appearing in browser network requests.
- Embed your numeric store ID directly in the API Connector root URL rather than passing it as a parameter per call — this scopes all calls to your store automatically and eliminates a common source of incorrect API paths.
- Always handle the `quantity = -1` case for unlimited-stock products in your UI — displaying '-1' to customers is confusing. Show 'In Stock' or 'Unlimited' using a conditional.
- Use `orderNumber` (not internal `id`) as the path parameter for all Ecwid order operations. These are different fields and only `orderNumber` works in API paths.
- Cache product data in Bubble's database for frequently browsed catalogs rather than fetching live for every page load — Ecwid's API rate limits are not publicly documented and repeated fetches from many concurrent users can trigger throttling.
- Apply Bubble privacy rules to any data type storing Ecwid order or customer data — restrict access to admin roles, not all authenticated users.
- Use Backend Workflows (paid Bubble plan) for all write operations (order status updates, product edits) to ensure they execute reliably and stay server-side.

## Use cases

### Embedded Ecwid Storefront in Bubble (Widget)

Add a fully functional Ecwid store to a Bubble page using the JS widget embed. Your Ecwid product catalog, shopping cart, and checkout flow appear inside your Bubble page — no API calls, no custom cart logic, works on any Bubble plan. Customers can browse, add to cart, and complete checkout without leaving your Bubble app.

Prompt example:

```
Show my entire Ecwid product catalog with working cart and checkout on this Bubble page, without building a custom shopping flow.
```

### Custom Product Catalog with Bubble Design

Build a custom-designed product catalog in Bubble using the Ecwid REST API. Fetch products from Ecwid's API, display them in a Bubble Repeating Group with your own layout and design system, and handle filtering, search, and pagination entirely in Bubble. Useful when the Ecwid widget's theme does not match your app's design.

Prompt example:

```
Show all Ecwid products in the 'Home Decor' category with a custom card layout, price filter, and 12-products-per-page grid — all in my Bubble design system.
```

### Order Management Admin Panel

Give your team a Bubble-based dashboard to view and manage Ecwid orders. Filter by fulfillment status, view order details and customer contact info, and update order status directly from Bubble without logging into Ecwid's control panel. Useful for customer support teams or fulfillment staff who need order access without full Ecwid admin permissions.

Prompt example:

```
Show all Ecwid orders with status AWAITING_PROCESSING from the last 14 days, sorted newest first, with customer name and shipping address.
```

## Troubleshooting

### HTTP 403 Forbidden when initializing the API Connector or making any API call

Cause: Your Ecwid plan does not include REST API access. The Free plan blocks all API calls with a 403 Forbidden error regardless of whether the access token is valid.

Solution: Log into your Ecwid Control Panel and check your current plan. The REST API requires Venture ($19/month) or a higher plan. Upgrade your plan, then go to Control Panel → Settings → API to get your access token — the API section may not appear at all on the Free plan. Update the Bearer token in your Bubble API Connector after upgrading.

### 'There was an issue setting up your call' during Initialize — no fields detected

Cause: The Initialize call returned an empty response or the Bearer token expired, or your Ecwid store has no products to initialize the products call against.

Solution: For the profile call: verify the Bearer token is valid by checking the Ecwid API documentation — tokens do not expire for Ecwid's standard API. For the products call: ensure you have at least one product in your Ecwid store. Add a test product in the Control Panel, then re-initialize. If the profile call fails too, verify the store ID in the root URL matches your numeric store ID exactly.

### Order update fails with 404 Not Found even though the order exists

Cause: You are using the internal `id` field from the GET orders response as the path parameter, but Ecwid's order path endpoints use `orderNumber`, not `id`.

Solution: In your GET /orders response, find the `orderNumber` field (a human-readable number like 1001) and use that value in your PUT /orders/{orderNumber} path. The `id` field is an internal identifier and is not valid as a path segment for order operations. Update your 'Update Order Status' API call in Bubble's API Connector so the path uses the `orderNumber` parameter.

### Product stock shows -1 in the Bubble UI

Cause: The product is set to unlimited stock in Ecwid. The `quantity` field returns -1 when `unlimited` is true for a product.

Solution: Add a conditional in Bubble on the stock display element: when 'Current Cell's Get Products's items first item's quantity = -1', change the text to 'Unlimited' (or hide the stock indicator). The `unlimited` boolean field is also available in the response and can be used as an alternative condition: when 'items first item's unlimited is yes', display 'In Stock' instead of the quantity value.

### The Ecwid widget embed in an HTML element shows nothing — the area is blank

Cause: The div ID in the HTML does not match the store ID in the script URL, or the script src URL contains the wrong store ID.

Solution: Check that BOTH the script src URL (?{storeId}) and the div id (my-store-{storeId}) contain your exact numeric store ID. A mismatch between these two values causes the script to load but render into a div that doesn't exist. The store ID is a pure number like 12345678 — no letters, no prefix. Preview the Bubble page and use browser developer tools to confirm the div element exists in the DOM and the script loaded without errors.

## Frequently asked questions

### Do I need a paid Ecwid plan to use it with Bubble?

It depends on which integration mode you use. The JS widget embed (where Ecwid renders the full storefront in a Bubble HTML element) works with any Ecwid plan including Free — no API access is needed. The REST API approach, which lets you fetch and manage products, orders, and customers from Bubble workflows and data types, requires the Venture plan ($19/month) or higher. Trying to use the API Connector with a Free plan account returns HTTP 403 Forbidden errors.

### What is the difference between the widget embed and the REST API approach?

The widget embed is the fastest setup: paste a two-line HTML snippet into a Bubble HTML element, and your full Ecwid storefront (products, cart, checkout) appears immediately. Ecwid handles everything including payment — you cannot customize the layout beyond Ecwid's themes, and you cannot access the store data from Bubble workflows. The REST API approach lets you build fully custom product displays, order management tools, and integrations with other Bubble data, but requires a paid Ecwid plan, more configuration, and Bubble API Connector setup.

### Why does my order update return 404 even though the order exists?

You are likely using the internal `id` field as the path parameter. Ecwid's order API paths use `orderNumber` (a human-readable number like 1001), not the internal `id` field. In your GET /orders response, find the `orderNumber` field and use that value in PUT /orders/{orderNumber} calls. The `id` field is not valid as a path segment for order operations.

### A product shows stock = -1 in my Bubble app. Is something wrong?

No — Ecwid returns -1 as the `quantity` value for products set to unlimited stock. The `unlimited` boolean field will be true for those products. In your Bubble UI, add a conditional on the stock display element: when quantity = -1 (or when unlimited = yes), show 'In Stock' or 'Unlimited' instead of the raw number.

### Do I need a paid Bubble plan for the Ecwid integration?

For the widget embed: no, any Bubble plan works. For the REST API: read-only operations (displaying products) can use client-side API calls on any Bubble plan. Write operations that you want to keep reliable and server-side (updating order status, syncing data on a schedule) require Backend Workflows, which are a paid Bubble plan feature.

### How do I find my Ecwid Store ID?

Your Store ID is the numeric value in your Ecwid Control Panel URL. When you log in to Ecwid at my.ecwid.com, look at the URL — it contains your store ID as a number (e.g., https://my.ecwid.com/store/12345678 means your Store ID is 12345678). You need this number both in the embed script URL and in the API Connector base URL if using the REST API.

---

Source: https://www.rapidevelopers.com/bubble-integrations/ecwid
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/ecwid
