Skip to main content
RapidDev - Software Development Agency
bubble-integrationsBubble API Connector

Magento

Connecting Bubble to Magento uses a permanent Integration Token in a Private Bearer Authorization header — not the Admin token, which expires every 4 hours. The defining Bubble challenge is Magento's searchCriteria filter system: bracket-notation URL parameters like `searchCriteria[filterGroups][0][filters][0][field]=status` must be added as individual parameters in Bubble's API Connector, not collapsed into a single query string. Each bracket-key is a separate parameter entry.

What you'll learn

  • Why Magento Integration Tokens are preferred over Admin tokens for Bubble integrations and how to create them
  • How to identify which of Magento's four activation tokens is the correct Access Token to use as Bearer
  • How to configure the Bubble API Connector base URL and store-scope path segments for single and multi-store Magento
  • How to add Magento's searchCriteria bracket-notation filter parameters as individual entries in Bubble's API Connector
  • How to handle Magento configurable (variable) products where stock and price live on child Simple products, not the parent
  • How to update order status via POST /orders/{id}/comments instead of PUT to the full order object
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced22 min read2–4 hoursE-commerceLast updated July 2026RapidDev Engineering Team
TL;DR

Connecting Bubble to Magento uses a permanent Integration Token in a Private Bearer Authorization header — not the Admin token, which expires every 4 hours. The defining Bubble challenge is Magento's searchCriteria filter system: bracket-notation URL parameters like `searchCriteria[filterGroups][0][filters][0][field]=status` must be added as individual parameters in Bubble's API Connector, not collapsed into a single query string. Each bracket-key is a separate parameter entry.

Quick facts about this guide
FactValue
ToolMagento
CategoryE-commerce
MethodBubble API Connector
DifficultyAdvanced
Time required2–4 hours
Last updatedJuly 2026

Magento for Bubble — Integration Tokens, searchCriteria syntax, and enterprise-scale considerations

Magento is the most complex e-commerce API covered in this guide. It is designed for enterprise operations — multi-store catalogs, B2B pricing tiers, configurable products with child SKUs, and a filter query system that looks like no other API. Bubble founders encounter it when a client's existing store is on Magento and they need to build a custom UI or operations tool on top of it.

The authentication choice matters immediately. Magento offers Admin user tokens (POST to `/V1/integration/admin/token` with username and password) — these expire after 4 hours and require your admin credentials in the request body, which is a security risk. The better choice for Bubble is an **Integration Token**: created in Magento's System → Extensions → Integrations panel with scoped resource permissions, it is permanent (does not expire) and uses the principle of least privilege — you choose exactly which APIs the token can access.

During Integration activation, Magento generates four token values: Consumer Key, Consumer Secret, Access Token, and Access Token Secret. Only the **Access Token** is used as the Bearer token in Bubble's API Connector. Using Consumer Key or Consumer Secret instead causes a 401 error with no explanation.

The searchCriteria filter system is Magento's most distinctive API characteristic. Instead of `?status=pending`, Magento uses `?searchCriteria[filterGroups][0][filters][0][field]=status&searchCriteria[filterGroups][0][filters][0][value]=pending&searchCriteria[filterGroups][0][filters][0][conditionType]=eq`. In Bubble's API Connector, each bracket-key must be a separate URL parameter — you cannot combine them into one parameter. This means a filter with 3 criteria requires adding 9+ individual parameter entries in the call editor.

For multi-store Magento, the store code is a URL path segment — `/rest/default/V1/` for the default store or `/rest/{store_code}/V1/` for other stores. Parameterize this in Bubble using a state variable for the store code.

Integration method

Bubble API Connector

Bubble API Connector with a Magento Integration Token in a Private Bearer Authorization header; Magento's bracket-notation searchCriteria URL parameters added individually in the API Connector call editor.

Prerequisites

  • Magento Open Source or Adobe Commerce installation with admin access (System → Extensions → Integrations menu available)
  • Your Magento store's domain and the REST API base URL (typically https://yourstore.com/rest)
  • The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' → Install)
  • A list of the Magento REST API resources your Bubble app needs (orders, catalog, customers, inventory) — you'll scope these in the Integration settings
  • For Adobe Commerce Cloud: confirmation from your IT team that Bubble's server IP ranges are whitelisted at the WAF/CDN layer

Step-by-step guide

1

Create a Magento Integration and obtain the Access Token

Log in to your Magento admin panel at `yourstore.com/admin`. In the left sidebar, navigate to System → Extensions → Integrations. Click 'Add New Integration.' Fill in: - **Name**: give it a descriptive name like 'Bubble App Integration' - **Email**: enter a contact email (for notifications if the integration is revoked) - **Current User Identity Verification**: you may need to enter your admin password to confirm identity Switch to the 'API' tab in the Integration form. This is where you scope the token's access: - Under 'Resource Access,' select 'Custom' - Check the resources your Bubble app needs. For an order management dashboard: Sales (Orders, Shipments, Invoices), Catalog (Products, Categories), Customer (Customers). Do not grant 'All' unless absolutely required — least-privilege scoping reduces risk. Click 'Save.' Magento brings you back to the Integrations list — find your new integration and click 'Activate.' Magento shows the 'Integration Tokens for Extensions' popup with four values: 1. Consumer Key 2. Consumer Secret 3. **Access Token** ← this is the one you need 4. Access Token Secret Copy only the **Access Token** (the third value in the popup). This is what you paste into Bubble as the Bearer token. Consumer Key and Consumer Secret are for OAuth-based integrations — using them as Bearer causes 401 errors. Click 'Done' to close the popup. If you lose the Access Token, you must deactivate and re-activate the integration to generate new tokens — there is no 'show token' option.

magento_integration_token.txt
1// Magento Integration activation generates 4 values:
2// 1. Consumer Key: Use only for OAuth-based integrations
3// 2. Consumer Secret: Use only for OAuth-based integrations
4// 3. Access Token: ← USE THIS as the Bearer token in Bubble
5// 4. Access Token Secret: Use only for OAuth-based integrations
6
7// Correct Bearer format in Bubble API Connector:
8// Authorization: Bearer [Access Token value] // mark Private
9
10// Base REST API URL formats:
11// Single default store: https://yourstore.com/rest/default/V1/
12// Multi-store by code: https://yourstore.com/rest/{store_code}/V1/
13// All stores (admin): https://yourstore.com/rest/all/V1/
14
15// Verify access (test from browser with curl):
16// curl -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
17// https://yourstore.com/rest/default/V1/store/storeConfigs
18// Expected: JSON array of store configuration objects

Pro tip: When selecting API scopes for the Integration, start with read-only access first (check only 'Get' operations under each resource). Test your Bubble integration fully. Then return to the Integration settings to add write access (PUT, POST operations) only for the specific resources your workflows need to modify. This staged approach prevents accidental data changes during development.

Expected result: The Magento Integration is activated and shows 'Active' status in System → Extensions → Integrations. You have copied the Access Token (not Consumer Key or Consumer Secret). The token is ready to paste into Bubble's API Connector.

2

Configure the Bubble API Connector for Magento

In your Bubble editor, go to Plugins → API Connector. Click 'Add another API' and name it 'Magento.' Set the base URL to `https://yourstore.com/rest` — this stops at `/rest`, not including the store scope or `/V1/`. The store scope and version go in each individual call's URL path. In the shared headers section for this API group, add: - Header name: `Authorization`, Value: `Bearer YOUR_ACCESS_TOKEN` — paste your Access Token after 'Bearer ', then check the **Private** checkbox - Header name: `Content-Type`, Value: `application/json` - Header name: `Accept`, Value: `application/json` Now add the Initialize Call. Click 'Add another call' and name it 'Get Store Configs.' Set method GET and URL path `/default/V1/store/storeConfigs`. This endpoint returns store configuration objects — safe to use as Initialize because it is read-only and returns useful data (store name, website ID, locale, base_currency_code). Click Initialize call. Magento returns a JSON array of store configuration objects. Bubble detects the array fields. If the Initialize call returns a 401, your Access Token is wrong (check you are using Access Token, not Consumer Key). If it returns 403, the Integration scope does not include Store configuration — add 'Stores' under API scopes and re-activate. For multi-store Magento: add a state variable `magento_store_code` (text, default 'default') on your Bubble pages and reference it in each call's URL path. In the URL field, type `/` + the state variable + `/V1/products` etc. Bubble evaluates the URL dynamically per workflow run.

magento_api_connector.json
1// Bubble API Connector: Magento
2// Base URL: https://yourstore.com/rest
3// (do NOT include /default/V1/ here — it goes in each call)
4//
5// Shared Headers:
6// Authorization: Bearer YOUR_ACCESS_TOKEN // mark Private
7// Content-Type: application/json
8// Accept: application/json
9//
10// Initialize Call: GET /default/V1/store/storeConfigs
11//
12// Expected response:
13// [
14// {
15// "id": 1,
16// "code": "default",
17// "website_id": 1,
18// "locale": "en_US",
19// "base_currency_code": "USD",
20// "default_display_currency_code": "USD",
21// "timezone": "America/Chicago",
22// "weight_unit": "lbs",
23// "base_url": "https://yourstore.com/",
24// "base_link_url": "https://yourstore.com/",
25// "base_static_url": "https://yourstore.com/pub/static/version1/",
26// "base_media_url": "https://yourstore.com/pub/media/"
27// }
28// ]

Pro tip: Set the base URL to just `https://yourstore.com/rest` — not `/rest/V1/` or `/rest/default/V1/`. Keeping the version and store scope in individual call paths makes it easier to switch between store scopes (default, specific store code, 'all') and API versions without reconfiguring the entire connector.

Expected result: The Magento API Connector initializes successfully. The Initialize Call returns an array of store config objects with locale, currency, and URL fields. The Authorization header shows the Access Token marked Private in the shared headers.

3

Build order list and filter calls using Magento's searchCriteria syntax

Magento's list endpoints use a bracket-notation filter system called searchCriteria. Unlike standard REST APIs where you pass `?status=pending`, Magento requires a nested bracket structure: ``` ?searchCriteria[filterGroups][0][filters][0][field]=status &searchCriteria[filterGroups][0][filters][0][value]=pending &searchCriteria[filterGroups][0][filters][0][conditionType]=eq ``` In Bubble's API Connector, these cannot be passed as a single URL parameter — you must add each bracket-key as a **separate URL parameter entry** in the call editor. Add a new call named 'Get Orders.' Set method GET, URL `/default/V1/orders`. Now add each filter parameter as individual entries: 1. Parameter: `searchCriteria[filterGroups][0][filters][0][field]`, Value: `status` (or make it dynamic) 2. Parameter: `searchCriteria[filterGroups][0][filters][0][value]`, Value: `pending` (dynamic) 3. Parameter: `searchCriteria[filterGroups][0][filters][0][conditionType]`, Value: `eq` 4. Parameter: `searchCriteria[currentPage]`, Value: `1` (dynamic) 5. Parameter: `searchCriteria[pageSize]`, Value: `20` (dynamic) 6. Parameter: `searchCriteria[sortOrders][0][field]`, Value: `created_at` 7. Parameter: `searchCriteria[sortOrders][0][direction]`, Value: `DESC` For the Initialize call, fill all dynamic fields with real values (status=pending, page=1, etc.) so Magento returns actual order data. Magento order list response: `{ "items": [ {...order objects...} ], "total_count": 247, "search_criteria": {...} }`. Map `items` in the API Connector to get the order list. Use `total_count` to build pagination — divide by pageSize and create a page number state variable. Magento's conditionType values: `eq` (equals), `neq` (not equals), `like` (contains, use `%value%`), `gteq` (greater than or equal), `lteq` (less than or equal), `in` (any of, comma-separated values), `notnull` (field exists). Standard operators like `>=` or `contains` do not work and return empty results without an error.

magento_orders_call.json
1// Magento → Get Orders
2// Method: GET
3// URL: /default/V1/orders
4//
5// URL Parameters (each as a separate entry in Bubble's API Connector):
6// searchCriteria[filterGroups][0][filters][0][field] = status
7// searchCriteria[filterGroups][0][filters][0][value] = pending (dynamic)
8// searchCriteria[filterGroups][0][filters][0][conditionType] = eq
9// searchCriteria[currentPage] = 1 (dynamic)
10// searchCriteria[pageSize] = 20
11// searchCriteria[sortOrders][0][field] = created_at
12// searchCriteria[sortOrders][0][direction] = DESC
13//
14// To add a date range filter (add as filterGroups[1]):
15// searchCriteria[filterGroups][1][filters][0][field] = created_at
16// searchCriteria[filterGroups][1][filters][0][value] = 2026-01-01 00:00:00
17// searchCriteria[filterGroups][1][filters][0][conditionType] = gteq
18//
19// Response:
20// {
21// "items": [
22// {
23// "base_grand_total": 59.98,
24// "grand_total": 59.98,
25// "customer_email": "john@example.com",
26// "customer_firstname": "John",
27// "customer_lastname": "Doe",
28// "increment_id": "000000042",
29// "status": "pending",
30// "created_at": "2026-01-27 14:32:00",
31// "items": [ { "sku": "WT09-XS-Purple", "qty_ordered": 2, "row_total": 59.98 } ]
32// }
33// ],
34// "total_count": 247
35// }

Pro tip: filterGroups use AND logic between groups, OR logic within a group's filters array. To filter orders that are EITHER pending OR processing, use filterGroups[0][filters][0] for pending and filterGroups[0][filters][1] for processing — both in the same group. To filter orders that are pending AND created after a date, use filterGroups[0] for status and filterGroups[1] for the date — separate groups.

Expected result: The Get Orders call initializes successfully, returning an items array with order objects and a total_count. Bubble detects the nested fields: increment_id, customer_email, grand_total, status, and created_at. A Repeating Group bound to this call shows a list of Magento orders filtered by the status parameter.

4

Build product catalog calls and handle configurable product stock

Add a call named 'Get Products' for the product catalog. Method GET, URL `/default/V1/products`. Add searchCriteria parameters: - `searchCriteria[filterGroups][0][filters][0][field]` = `status` - `searchCriteria[filterGroups][0][filters][0][value]` = `1` (enabled products only) - `searchCriteria[filterGroups][0][filters][0][conditionType]` = `eq` - `searchCriteria[pageSize]` = `20` - `searchCriteria[currentPage]` = `1` (dynamic) Magento product response: `{ "items": [{...}], "total_count": N, "search_criteria": {...} }`. Each product has `sku`, `name`, `price`, `type_id` (simple, configurable, grouped, virtual), `status`, `weight`, and a `custom_attributes` array. For **configurable products** (products with size/color variations): the parent configurable product has a NULL or zero price and NULL stock — price and stock live on child Simple products. To get child SKUs: GET `/default/V1/configurable-products/{sku}/children`. Each child has its own price and stock quantity. For stock quantity: GET `/default/V1/stockStatuses?searchCriteria[filterGroups][0][filters][0][field]=sku&searchCriteria[filterGroups][0][filters][0][value]={sku}&searchCriteria[filterGroups][0][filters][0][conditionType]=eq`. The response includes `items[0].qty` and `items[0].stock_status` (1=in stock, 0=out of stock). For a product price update: PUT `/default/V1/products/{sku}` with a body containing the complete product object — Magento requires full-object PUT, not partial updates. Fetch the product first with GET `/default/V1/products/{sku}`, modify the price field in a Bubble state, then PUT the complete modified object. For bulk price updates across many products, use 'Schedule API Workflow on a list' in Bubble to avoid the 30-second timeout.

magento_products_call.json
1// Magento → Get Products
2// Method: GET
3// URL: /default/V1/products
4//
5// URL Parameters:
6// searchCriteria[filterGroups][0][filters][0][field] = status
7// searchCriteria[filterGroups][0][filters][0][value] = 1
8// searchCriteria[filterGroups][0][filters][0][conditionType] = eq
9// searchCriteria[pageSize] = 20
10// searchCriteria[currentPage] = 1 (dynamic)
11//
12// Response (items array structure):
13// {
14// "items": [
15// {
16// "id": 2048,
17// "sku": "WT09-XS-Purple",
18// "name": "Breathe-Easy Tank",
19// "price": 34.00,
20// "type_id": "simple",
21// "status": 1,
22// "visibility": 4,
23// "custom_attributes": [
24// { "attribute_code": "description", "value": "..." },
25// { "attribute_code": "color", "value": "Purple" }
26// ]
27// }
28// ],
29// "total_count": 1854
30// }
31
32// Get configurable product children (for sizes/colors):
33// GET /default/V1/configurable-products/{parent_sku}/children
34// Returns array of simple product objects with individual price + stock
35
36// Get stock for a specific SKU:
37// GET /default/V1/stockStatuses?searchCriteria[filterGroups][0][filters][0][field]=sku
38// &searchCriteria[filterGroups][0][filters][0][value]={sku}
39// &searchCriteria[filterGroups][0][filters][0][conditionType]=eq

Pro tip: Magento's `custom_attributes` array is a list of `{ attribute_code: string, value: any }` objects. To display a specific custom attribute in Bubble, filter the `custom_attributes` list by `attribute_code` in your Bubble expression. For example, to get product description, find the item in the list where attribute_code = 'description' and take its value.

Expected result: The Get Products call initializes with an items array of Magento products including id, sku, name, price, and type_id. A Repeating Group in Bubble shows the product catalog. For a configurable product, the children call returns an array of simple products each with their own price, stock, and attribute values.

5

Update order status using POST /orders/{id}/comments

Updating an order's status in Magento from Bubble has a simpler path than most guides describe. The correct approach is NOT a PUT to the full `/V1/orders/{id}` endpoint (which requires a complete order object body). Instead, POST to `/V1/orders/{id}/comments` with a `statusHistory` body — this is the same endpoint Magento's own admin panel uses when a staff member changes an order status. Add a call named 'Update Order Status.' Set method POST, URL `/default/V1/orders/<id>/comments` where `<id>` is a dynamic text parameter for the Magento order ID (the numeric `entity_id`, not the `increment_id` display number). Set the body type to JSON. The required body structure: ```json { "statusHistory": { "comment": "Status updated from Bubble", "is_customer_notified": 0, "is_visible_on_front": 0, "parent_id": null, "status": "complete" } } ``` Set `is_customer_notified` to `0` to suppress customer email notifications during batch updates or testing; set to `1` when you want Magento to email the customer about the status change. For the Initialize call, you need a real Magento order ID (use one from your test orders list). The response is just `true` on success. For Bubble workflow: when a warehouse operator clicks 'Mark Shipped' on an order in your dashboard Repeating Group, use a workflow action: 'Plugins → API Connector → Magento → Update Order Status' with the entity_id from the current cell's data and status='complete'. Add a second workflow step to refresh the Repeating Group data or update the cell's displayed status via a custom state.

magento_update_order_status.json
1// Magento → Update Order Status
2// Method: POST
3// URL: /default/V1/orders/<id>/comments
4// (<id> = dynamic: Magento order entity_id, e.g. 1234)
5//
6// Body (JSON):
7{
8 "statusHistory": {
9 "comment": "<dynamic: optional internal note>",
10 "is_customer_notified": 0,
11 "is_visible_on_front": 0,
12 "parent_id": null,
13 "status": "<dynamic: new status string>"
14 }
15}
16
17// Common Magento order status values:
18// pending → new order, not yet processed
19// processing → payment confirmed, being fulfilled
20// complete → shipped and delivered
21// closed → refunded/returned
22// canceled → canceled before fulfillment
23// holded → held for manual review
24// payment_review → payment flagged for review
25
26// Note: use the order's entity_id (numeric, e.g. 1234)
27// NOT the increment_id (display number, e.g. 000001234)
28// The entity_id is in the 'id' field of the GET /V1/orders response

Pro tip: Magento's increment_id (the customer-facing order number like #000001234) is different from the entity_id (the internal numeric ID like 1234). The /orders/{id}/comments endpoint requires the entity_id. In Bubble, when you load orders with GET /V1/orders, both fields are in the response — store the `id` field (entity_id) in your Repeating Group cell's data for use in status update calls.

Expected result: The Update Order Status call returns `true` on success. In Magento admin, the order shows the new status and an internal comment entry in the order history. The call completes in under 2 seconds for individual orders.

6

Handle Adobe Commerce Cloud IP whitelisting and test the full integration

Before going live, test the full Bubble-to-Magento integration and address Adobe Commerce Cloud-specific requirements if applicable. **Adobe Commerce Cloud WAF:** Adobe Commerce Cloud (Magento hosted by Adobe) includes a Web Application Firewall (WAF) and CDN that may block API calls from unrecognized IP ranges — including Bubble's server IPs. If your API calls succeed with curl from your local machine but fail with HTTP 403 from Bubble, IP whitelisting is likely the cause. Contact your Magento system administrator or Adobe Commerce support to whitelist Bubble's IP ranges. As Bubble uses a multi-tenant infrastructure, the specific IP ranges vary — Bubble publishes current server IP ranges in their documentation. Request whitelisting of these ranges at the CDN/WAF layer, not just at the Magento application level. **End-to-end testing checklist:** 1. In Bubble's Logs tab → Workflow logs, verify all GET calls return 200 with populated data 2. Test searchCriteria filters by changing status values and verifying the returned orders match the filter 3. Test the order status update on a sandbox or staging Magento environment before production 4. For multi-store setups, verify that switching the store_code state variable returns products from the correct store 5. Test pagination: set currentPage to 2 and verify different products appear 6. Check Bubble's Workload Unit consumption in the Logs — complex searchCriteria calls and bulk product loads consume significant WU on high-traffic pages For complex enterprise Magento integrations — multi-source inventory, B2B quote management, ERP sync — RapidDev's team has experience with Magento API architecture at scale. Reach out at rapidevelopers.com/contact for a scoping call.

magento_multistore_and_testing.txt
1// Multi-store Magento: switch store scope dynamically
2// Add a Dropdown on the page, data source = API Connector → Magento → Get Store Configs
3// Display field: code
4// On change: Set state 'magento_store_code' to Dropdown's value
5//
6// In all API Connector call URLs, reference the state:
7// URL: /<magento_store_code state>/V1/orders
8// URL: /<magento_store_code state>/V1/products
9//
10// Bubble Logs → check for WU consumption per call:
11// - Simple GET /orders (1 page): ~15-30 WU
12// - GET /products (large catalog): ~20-50 WU per page
13// - POST /orders/{id}/comments: ~10-20 WU
14//
15// Adobe Commerce Cloud IP whitelist request:
16// Provide Bubble's server IP ranges to your Magento admin for WAF whitelisting
17// Check Bubble documentation for current server IP ranges to whitelist
18// WAF whitelisting is done at the CDN level (Fastly, Cloudflare), not Magento config

Pro tip: Use a Magento staging environment (most enterprise Magento installations have one) for all Bubble integration development. Staging environments have separate Integration Tokens — create a staging Integration with the same scopes as production. Switch credentials when going live. Never test write operations (POST, PUT, DELETE) on a production Magento store without a staging run first.

Expected result: All Magento API calls from Bubble return 200 with correct data. searchCriteria filters return orders matching the specified criteria. Order status updates post successfully and appear in Magento admin order history. Multi-store switching loads products from the correct Magento store view.

Common use cases

Custom Magento order management dashboard for store operators

Build a Bubble operations panel that gives your team filtered views of Magento orders by status, date range, and shipping region — with the ability to update order status, add notes, and mark as shipped — all without requiring Magento admin access. The Bubble interface can be customized for specific roles (warehouse staff, customer support, fulfillment) with tailored workflows.

Bubble Prompt

On the dashboard page, bind a Repeating Group to the GET /default/V1/orders call with searchCriteria filters for status=processing and sort by created_at descending. Show each order's increment_id, customer_firstname, customer_lastname, grand_total, and status. Add a 'Mark Shipped' button that triggers POST /default/V1/orders/{id}/comments with status=complete and a tracking note.

Copy this prompt to try it in Bubble

Magento product catalog browser with multi-store support

Build a Bubble app for merchandising teams to browse and edit the Magento product catalog across multiple stores — viewing product names, descriptions, prices, and stock levels with the ability to filter by category and update pricing. Use a store-selector Dropdown in Bubble to switch between Magento store views dynamically.

Bubble Prompt

Add a Dropdown to the page with values from GET /V1/store/storeConfigs (returns all store codes). Bind a Repeating Group to GET /{selected_store}/V1/products with searchCriteria filters for type_id=simple and status=1. Each cell shows sku, name, price, and qty. A price-edit input triggers PUT /{selected_store}/V1/products/{sku} with the updated price object.

Copy this prompt to try it in Bubble

Customer self-service portal for Magento shoppers

Build a custom Bubble customer portal where shoppers can view their Magento order history, track shipments, download invoices, and initiate returns — with a better mobile UX than Magento's default customer account pages. Authenticate customers via a dedicated customer token endpoint and use it for customer-scoped API calls.

Bubble Prompt

On customer login, POST to /V1/integration/customer/token with the customer's email and password to get a customer token. Store it in a Bubble state. Use this token (instead of the Integration Token) in the Authorization header for GET /V1/orders/mine to load that customer's orders. Display order history, items, and tracking information.

Copy this prompt to try it in Bubble

Troubleshooting

Magento API returns 401 Unauthorized even though the Authorization header looks correct

Cause: You are using the Consumer Key or Consumer Secret as the Bearer token instead of the Access Token. Magento generates four token values during Integration activation; only the 'Access Token' (third in the list) is used as Bearer. Consumer Key and Consumer Secret are for OAuth-based request signing, which is a different authentication flow.

Solution: Go to Magento admin → System → Extensions → Integrations → find your Integration → click 'Edit.' If the integration is already activated, deactivate it and re-activate to see the popup with all four token values again. In the popup, the 'Access Token' field is the third row. Copy its value (a long alphanumeric string) and update the Bearer token in Bubble's API Connector Authorization header. The Consumer Key looks different — it's shorter and formatted differently from the Access Token.

'There was an issue setting up your call' on any Magento GET endpoint — no response fields detected

Cause: The Initialize call returned an error (401, 403, or 404 with an HTML error page) rather than valid JSON. Bubble cannot detect response schema from error responses. Common causes: Integration Token is wrong (see above), the Integration scope does not include the requested resource, or the API endpoint path is incorrect.

Solution: Test the API call directly in a browser or REST client first: GET `https://yourstore.com/rest/default/V1/store/storeConfigs` with `Authorization: Bearer YOUR_ACCESS_TOKEN`. If it returns a JSON response, the credentials are correct and the issue is with the specific endpoint path in Bubble. If it returns 401, the token is wrong. If it returns 403, the Integration scope does not include this resource — add it in System → Extensions → Integrations → Edit → API tab.

Magento searchCriteria filter returns empty items array even though matching orders exist

Cause: An incorrect conditionType value is being used. Magento uses Magento-specific conditionType strings: `eq`, `neq`, `like`, `gteq`, `lteq`, `in`, `notnull`. Using standard operators like `>=`, `contains`, `!=`, or `>` causes Magento to silently return empty results with no error — the conditionType is simply ignored or falls back to an unrecognized type.

Solution: Check every filter's conditionType parameter value in Bubble's API Connector. Replace any non-Magento operators with the correct Magento equivalents: use `eq` for exact match, `gteq` for 'greater than or equal', `lteq` for 'less than or equal', `like` with percent wildcards for partial text match (e.g., value=`%purple%`). Also verify that the filter field name exactly matches Magento's internal field name (e.g., `created_at` not `date_created`, `entity_id` not `id`).

Bubble API calls to Magento fail with 403 Forbidden when called from Bubble but succeed from local curl

Cause: Adobe Commerce Cloud's WAF (Web Application Firewall) is blocking requests from Bubble's server IP ranges. Adobe Commerce Cloud includes CDN and WAF layers (typically Fastly) that may not have Bubble's server IPs in their allowlist. This is specific to Adobe Commerce Cloud, not self-hosted Magento.

Solution: Contact your Magento/Adobe Commerce admin or Adobe Support to add Bubble's server IP ranges to the WAF allowlist at the CDN layer. Bubble's server IPs are available in Bubble's documentation. This is a network-level change, not a Magento configuration change — it must be done by someone with CDN/WAF admin access. As a temporary workaround during testing, a Cloudflare Worker proxy can forward Bubble's requests from a whitelisted IP.

Best practices

  • Use a Magento Integration Token with the minimum required API scopes — not 'All Resources.' Scope the Integration to exactly the resources your Bubble app reads and writes: if your dashboard only shows orders and products, scope to Sales and Catalog only. This limits the blast radius if the token is ever compromised.
  • Never use Admin user tokens (POST /V1/integration/admin/token with username/password) in Bubble integrations. Admin tokens expire after 4 hours and require embedding admin credentials in an API call — Integration Tokens are permanent, scoped, and do not expose admin passwords.
  • Add Magento's base URL `/rest` as the API Connector base URL and put the store scope (`/default/V1/`) in each individual call path — not in the base URL. This allows you to parameterize the store code with a Bubble state variable for multi-store switching without duplicating the entire API Connector configuration.
  • Always use `searchCriteria[pageSize]` and `searchCriteria[currentPage]` on all Magento list calls. Without pagination, Magento defaults to returning a small number of items or a very large dataset depending on the endpoint — large product or order responses can hit Bubble's response size limits and cause workflow timeouts.
  • For order status updates, use POST /orders/{id}/comments (the statusHistory endpoint) rather than PUT /orders/{id}. The comments endpoint is simpler, does not require a full object body, and is what Magento's admin UI uses internally — it is less likely to cause unintended side effects on complex order objects.
  • Test on a Magento staging environment before making any write operations on production. Magento staging environments should have identical Integration Token scope — create a separate Integration on staging with the same permissions. Test all searchCriteria filter combinations, pagination, and status updates on staging before pointing to production.
  • Monitor Workload Unit consumption in Bubble's Logs tab. Magento calls with complex searchCriteria filters, large product catalogs, and nested response structures consume more WU than simple API calls. Cache read-heavy data (product catalog, category list) in Bubble Data Things to reduce per-pageload API calls.

Alternatives

Frequently asked questions

What is the difference between Magento Open Source and Adobe Commerce Cloud for this integration?

The Integration Token setup, searchCriteria syntax, and API endpoints work identically in both. The difference is infrastructure: Adobe Commerce Cloud (the hosted SaaS version) includes a CDN and WAF that may block Bubble's server IP ranges, requiring an IP whitelist request to Adobe. Self-hosted Magento Open Source has no WAF — Bubble calls reach Magento directly without IP restrictions. Also, Adobe Commerce (paid) includes additional API endpoints for B2B features, staging environments, and advanced inventory that Open Source does not have.

Can I use this integration on a Bubble free plan?

Yes for read-only operations (GET products, GET orders). The API Connector works on all Bubble plans. There is no backend workflow requirement for the Magento API Connector integration — all calls are outbound from Bubble, not inbound webhooks. The free plan limitation applies if you want to receive Magento webhooks in a Bubble Backend Workflow, but Magento's webhook feature is less commonly used — most Bubble integrations poll Magento rather than receiving pushes.

How do I filter products by category in Magento?

Magento product categories use category_id — not category name. First, fetch categories with GET /V1/categories to get the ID for the category you want. Then filter products with searchCriteria[filterGroups][0][filters][0][field]=category_id, value=your_category_id, conditionType=eq. Add this as individual parameters in the Bubble API Connector call. Note: category_id filtering uses Magento's EAV attribute system, so ensure the Integration scope includes Catalog Categories.

My Magento integration works on smaller product pages but times out on large catalogs. What should I do?

Magento's large product catalogs can return slow responses on complex filter queries, especially on shared hosting. In Bubble, reduce `searchCriteria[pageSize]` to 10-20 items per page — smaller pages are faster and more reliable. For bulk catalog operations (price updates, stock syncs), use Bubble's 'Schedule API Workflow on a list' to distribute work across multiple sequential workflow executions rather than one large single workflow. Also enable Magento's full-page cache if it is not already active — it significantly speeds up read operations.

Do I need a paid Bubble plan for this integration?

No — all outbound API Connector calls to Magento work on the Bubble free plan. The only feature that requires a paid plan is receiving inbound webhooks via Backend Workflows. Since Magento supports webhooks (available via plugins or custom modules), a paid plan is needed only if you want real-time push notifications from Magento to Bubble. For most use cases (dashboards, product browsers, order management), the free plan is sufficient.

RapidDev

Talk to an Expert

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

Book a free consultation

Integrations are where projects stall

We wire Bubble integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

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.