Connecting Bubble to Salesforce Commerce Cloud (SFCC) requires a mandatory Cloud Function proxy (Firebase or Cloudflare Worker) to run the SLAS PKCE OAuth flow and mint short-lived shopper tokens — Bubble cannot generate PKCE values or hold SLAS credentials natively. SFCC is enterprise-only with no free tier or self-serve sign-up. Tokens expire in approximately 30 minutes, making a Recurring Backend Workflow for proactive refresh essential. This is the most advanced integration in the E-commerce category.
| Fact | Value |
|---|---|
| Tool | Salesforce Commerce Cloud |
| Category | E-commerce |
| Method | Backend Workflow (Webhooks) |
| Difficulty | Advanced |
| Time required | 1–2 days |
| Last updated | July 2026 |
The Enterprise Integration That Needs Infrastructure Before Configuration
Salesforce Commerce Cloud is the enterprise outlier in the E-commerce integration category, and it is critical to set expectations correctly upfront: SFCC is not a self-serve platform. If you are building a proof of concept hoping to get SFCC access later, or if you are exploring whether SFCC might work for your use case, this integration will not be possible without an active SFCC enterprise contract or sandbox access through a Salesforce partner. Typical SFCC enterprise contracts start at $150,000+ annually, and sandbox environments are provided as part of those contracts. If you already have SFCC access, this tutorial explains the full technical architecture. The core challenge: SFCC's authentication system (SLAS — Shopper Login and API Access Service) uses OAuth 2.0 PKCE to mint short-lived shopper tokens. SLAS client credentials must live in a server-side environment — they cannot be placed in Bubble's API Connector headers without being exposed. This makes a server-side proxy function mandatory: you deploy a Firebase Cloud Function (or Cloudflare Worker) that holds SLAS credentials, runs the PKCE flow, and returns only the short-lived Bearer token to Bubble. Bubble's Backend Workflow calls this proxy, stores the returned token and its expiry, and then uses it as the Bearer header for SCAPI Shopper API calls. Tokens expire in approximately 30 minutes (your org's exact setting is in Salesforce Business Manager under SLAS configuration), so a Recurring Backend Workflow that checks and refreshes tokens every 25 minutes is not optional. The SCAPI itself (once you have a valid token) is well-documented and consistent — product search, product detail, basket management, and checkout each have clear endpoint schemas. The complexity lies entirely in the authentication layer and the infrastructure prerequisite.
Integration method
Backend Workflows handle SLAS OAuth token minting via a mandatory Firebase Cloud Function (or Cloudflare Worker) proxy, plus proactive token refresh on a Recurring schedule. The API Connector then calls SCAPI Shopper endpoints using the returned Bearer token.
Prerequisites
- An active Salesforce Commerce Cloud enterprise contract or sandbox access through a Salesforce partner — there is no free tier, trial, or self-serve sign-up for SFCC
- Your SFCC org credentials from Salesforce Business Manager: org ID, shortcode (alphanumeric string visible in your SCAPI base URL), site ID, and SLAS client ID
- Access to deploy a Firebase Cloud Function or Cloudflare Worker — required as the mandatory SLAS token-minting proxy; cannot be substituted with Bubble-native solutions
- A Bubble app on a paid plan — Backend Workflows (API Workflows) and Recurring Backend Workflows are required for token management; these are not available on Bubble's Free plan
- The API Connector plugin installed in your Bubble app (free, published by Bubble)
- Development experience with either Firebase Functions or Cloudflare Workers — the proxy function setup requires JavaScript/Node.js knowledge outside of Bubble
Step-by-step guide
Gather SFCC Credentials from Business Manager
Before touching Bubble, gather the SFCC credentials you need from your Salesforce Business Manager instance. Log in to Business Manager (your org's admin console). The following values are required: (1) Organization ID — found in Business Manager under Administration → Salesforce Commerce Cloud API Client → your client record, or in merchant tooling documentation; (2) Shortcode — the alphanumeric string that appears in your SCAPI base URL; it is typically visible in Business Manager under Administration → API Configuration or in your org's onboarding documentation; (3) Site ID — the identifier for your specific storefront site within the SFCC org (e.g., 'RefArch' for reference architecture sites, or a custom name); (4) SLAS Client ID — created in Business Manager under Administration → SLAS Administration → API Clients. When creating a SLAS API client, set the token TTL (how long tokens last — typically 1800 seconds = 30 minutes) and note whether you are using the guest (unauthenticated shopper) or registered (authenticated shopper) flow. For headless storefront builds, the guest flow is the starting point. The SLAS client may also have a client secret for registered shopper flows — if so, store it securely. Important upfront disclosure: if you are reading this tutorial without an active SFCC contract or partner sandbox, the integration cannot be completed. SFCC has no sandbox signup, no developer tier, and no API access outside of a commercial or partner relationship.
1// SFCC Base URL format — your shortcode goes where {shortcode} appears2// Example: if shortcode is 'abc123', your base URL is:3https://abc123.api.commercecloud.salesforce.com45// Key SFCC configuration values you need to collect:6// org_id: your org identifier (from Business Manager → Administration)7// shortcode: alphanumeric prefix in SCAPI base URL8// site_id: your storefront site identifier (e.g., RefArch)9// slas_client_id: from Business Manager → Administration → SLAS Administration → API Clients1011// Wrong shortcode = network error or 404, NOT a 40112// Verify shortcode before any API testingPro tip: Write down the shortcode from your SCAPI base URL before leaving Business Manager. Using the wrong shortcode produces a network error or 404 (not a 401), which looks like a connectivity problem rather than an auth problem. Verifying the shortcode first saves significant debugging time.
Expected result: You have all four required values documented: org_id, shortcode, site_id, and slas_client_id. You know the token TTL configured in your SLAS API Client settings. You are ready to deploy the proxy function.
Deploy the SLAS Token-Minting Cloud Function
This step requires deploying a server-side function outside of Bubble. SFCC's SLAS system uses PKCE OAuth, and Bubble cannot generate PKCE code_verifier/code_challenge pairs or hold SLAS credentials securely. A Firebase Cloud Function is the most accessible choice for most teams — it requires a Firebase project (free Spark plan is sufficient for the function; just billing must be enabled). Create a Firebase project at console.firebase.google.com. In the project, go to Functions and set up a new function using the Firebase CLI on your computer. The function needs two endpoints: (1) sfccGuestToken — takes no parameters, runs the SLAS PKCE guest-shopper flow (generate code_verifier, derive code_challenge, POST to SLAS token endpoint with the PKCE values), and returns only the access_token and its expiry; (2) sfccRefreshToken — takes the current refresh_token, calls SLAS token refresh, and returns the new access_token and refresh_token. Store all SLAS credentials (client_id, org_id, site_id, shortcode) in Firebase environment config or Cloud Secrets — never hardcode them in the function. The SLAS token endpoint is: https://{shortcode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/{org_id}/oauth2/token. Deploy the function with Firebase deploy --only functions. Note the function's HTTPS URL — you will use it in Bubble's API Connector as the auth proxy endpoint. If your team prefers Cloudflare Workers over Firebase, the same logic applies: a Worker holds credentials and serves the same two endpoints.
1// Firebase Cloud Function — SLAS Guest Token Minting2// File: functions/index.js3// Deploy with: firebase deploy --only functions45const functions = require('firebase-functions');6const axios = require('axios');7const crypto = require('crypto');89// Store these in Firebase config: firebase functions:config:set sfcc.client_id=... etc.10const SFCC_CLIENT_ID = functions.config().sfcc.client_id;11const SFCC_ORG_ID = functions.config().sfcc.org_id;12const SFCC_SITE_ID = functions.config().sfcc.site_id;13const SFCC_SHORTCODE = functions.config().sfcc.shortcode;1415function base64URLEncode(buffer) {16 return buffer.toString('base64')17 .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');18}1920exports.sfccGuestToken = functions.https.onRequest(async (req, res) => {21 res.set('Access-Control-Allow-Origin', '*');22 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }23 try {24 const code_verifier = base64URLEncode(crypto.randomBytes(32));25 const code_challenge = base64URLEncode(26 crypto.createHash('sha256').update(code_verifier).digest()27 );28 const tokenURL = `https://${SFCC_SHORTCODE}.api.commercecloud.salesforce.com` +29 `/shopper/auth/v1/organizations/${SFCC_ORG_ID}/oauth2/token`;30 const params = new URLSearchParams({31 grant_type: 'client_credentials',32 client_id: SFCC_CLIENT_ID,33 redirect_uri: 'http://localhost',34 code_verifier,35 code_challenge,36 code_challenge_method: 'S256',37 channel_id: SFCC_SITE_ID,38 hint: 'guest'39 });40 const response = await axios.post(tokenURL, params.toString(), {41 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }42 });43 res.json({44 access_token: response.data.access_token,45 refresh_token: response.data.refresh_token,46 expires_in: response.data.expires_in47 });48 } catch (error) {49 res.status(500).json({ error: error.message });50 }51});5253exports.sfccRefreshToken = functions.https.onRequest(async (req, res) => {54 res.set('Access-Control-Allow-Origin', '*');55 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }56 const { refresh_token } = req.body;57 try {58 const tokenURL = `https://${SFCC_SHORTCODE}.api.commercecloud.salesforce.com` +59 `/shopper/auth/v1/organizations/${SFCC_ORG_ID}/oauth2/token`;60 const params = new URLSearchParams({61 grant_type: 'refresh_token',62 refresh_token,63 client_id: SFCC_CLIENT_ID64 });65 const response = await axios.post(tokenURL, params.toString(), {66 headers: { 'Content-Type': 'application/x-www-form-urlencoded' }67 });68 res.json({69 access_token: response.data.access_token,70 refresh_token: response.data.refresh_token,71 expires_in: response.data.expires_in72 });73 } catch (error) {74 res.status(500).json({ error: error.message });75 }76});Pro tip: Test the deployed Firebase function directly (via curl or Postman) before connecting it to Bubble. Confirm it returns a valid access_token before proceeding. A function that works in isolation eliminates auth as a variable when debugging the Bubble API Connector setup.
Expected result: Two HTTPS Cloud Function endpoints are deployed and returning valid SLAS tokens. Testing the sfccGuestToken URL in a browser or API client returns JSON with an access_token, refresh_token, and expires_in. The function's URL is saved — you will use it in the next step.
Set Up Two API Connector Groups in Bubble
With the Cloud Function deployed and returning tokens, set up Bubble's API Connector with two groups. Open your Bubble app editor, go to Plugins tab → Add plugins → search 'API Connector' (published by Bubble) and install it. Group 1 — SFCCAuth: Click 'Add another API', name it 'SFCCAuth'. Set the root URL to your Firebase Cloud Function base URL (e.g., https://us-central1-yourproject.cloudfunctions.net). No shared headers needed — the function handles its own auth internally. Add one call: name it 'Get Guest Token', method POST, path /sfccGuestToken, no body parameters. Set the call's 'Use as' to 'Action'. Click 'Initialize call' — it should return the access_token, refresh_token, and expires_in fields. Group 2 — SFCCShop: Click 'Add another API', name it 'SFCCShop'. Set the root URL to https://{shortcode}.api.commercecloud.salesforce.com (replace shortcode with your actual shortcode). Add shared headers: Authorization with value 'Bearer [accessToken]' (check Private checkbox) where accessToken is a dynamic group-level parameter. Add an Accept: application/json header. This group will hold all your SCAPI Shopper API calls — product search, product detail, basket operations. The accessToken parameter will be supplied by your Bubble workflows from the stored SFCCSession token.
1// Group 1: SFCCAuth — points at Firebase Cloud Function2{3 "groupName": "SFCCAuth",4 "rootURL": "https://us-central1-YOUR-FIREBASE-PROJECT.cloudfunctions.net",5 "sharedHeaders": [],6 "calls": [7 {8 "name": "Get Guest Token",9 "method": "POST",10 "path": "/sfccGuestToken",11 "useAs": "Action"12 },13 {14 "name": "Refresh Token",15 "method": "POST",16 "path": "/sfccRefreshToken",17 "useAs": "Action",18 "bodyParams": [{ "name": "refresh_token", "dynamic": true }]19 }20 ]21}2223// Group 2: SFCCShop — points at SCAPI Shopper endpoints24{25 "groupName": "SFCCShop",26 "rootURL": "https://YOUR-SHORTCODE.api.commercecloud.salesforce.com",27 "sharedHeaders": [28 {29 "name": "Authorization",30 "value": "Bearer <accessToken dynamic>",31 "private": true32 },33 {34 "name": "Accept",35 "value": "application/json",36 "private": false37 }38 ],39 "groupParameters": [40 { "name": "accessToken", "description": "SLAS Bearer token from SFCCSession record" }41 ]42}Pro tip: The SFCCAuth group does NOT need the Bearer token header — your Cloud Function handles SLAS auth internally and returns only the token. Only the SFCCShop group needs the Bearer authorization header.
Expected result: Two API Connector groups appear in Bubble: SFCCAuth pointing at your Cloud Function and SFCCShop pointing at the SCAPI base URL with a Private Bearer authorization header. The 'Get Guest Token' call has been initialized and Bubble has detected the access_token and refresh_token fields.
Store Tokens in Bubble and Set Up the Token Lifecycle
Create a Bubble data type to manage the SLAS token lifecycle. Go to Data tab → Data types → Add a type named 'SFCCSession'. Add fields: access_token (text), refresh_token (text), token_expiry (date), user (User — optional, for multi-user apps). Apply privacy rules to this data type immediately: Data tab → Privacy → SFCCSession → set rule so that only the Current User who owns the record can read it. Create a Backend Workflow named 'SFCC_InitSession'. This workflow calls the SFCCAuth 'Get Guest Token' action, then creates or modifies an SFCCSession record: set access_token to the call's returned access_token value, set refresh_token to the returned refresh_token, set token_expiry to current date/time + the returned expires_in value in seconds (typically 1800 seconds). Trigger this workflow when your app loads for a new session — use the page's 'On page load' workflow to check if an SFCCSession record exists for the current user. If not, schedule the SFCC_InitSession Backend Workflow. For the refresh workflow, create 'SFCC_RefreshSession' that calls the SFCCAuth 'Refresh Token' action with the current user's stored refresh_token, then updates the SFCCSession record with the new access_token, refresh_token, and a new token_expiry. Set up a Recurring Backend Workflow (Settings → Backend Workflows → Recurring events) running every 25 minutes: it searches for SFCCSession records where token_expiry is within the next 5 minutes and calls SFCC_RefreshSession for each one. Recurring Backend Workflows are available on paid Bubble plans only.
1// SFCCSession data type fields:2// access_token (text) — current SLAS Bearer token for API calls3// refresh_token (text) — used to obtain new access_token when it expires4// token_expiry (date) — timestamp when access_token will expire (~30 min from issue)5// user (User) — links this session to a specific Bubble User (optional)67// Privacy rules to add immediately (Data tab → Privacy → SFCCSession):8// Rule: When Current User is This SFCCSession's user → allow read/modify9// This prevents any user from reading another user's SFCC token1011// Token expiry calculation:12// expires_in from SLAS response = 1800 (seconds, typically)13// token_expiry = Current Date/Time + 1800 seconds14// Bubble expression: Current date/time + 1800 seconds1516// Recurring Backend Workflow logic (every 25 minutes):17// Search SFCCSession where token_expiry < Current date/time + 5 minutes18// For each result: call SFCC_RefreshSession with that record's refresh_tokenPro tip: The token_expiry is approximately 30 minutes (1800 seconds) from when the token was issued, but verify your org's exact setting in Business Manager under SLAS API Client configuration — some orgs configure shorter or longer TTLs. Set your Recurring Backend Workflow to run at 25 minutes to ensure refresh happens before expiry even if there is workflow execution latency.
Expected result: The SFCCSession data type is created with access_token, refresh_token, and token_expiry fields. Privacy rules are set. The SFCC_InitSession and SFCC_RefreshSession Backend Workflows are configured. The Recurring Backend Workflow for token refresh is running every 25 minutes.
Add SCAPI Product Search and Product Detail Calls
Add SCAPI Shopper endpoints to the SFCCShop API Connector group. SCAPI product search and product detail have different JSON schemas and must be defined as separate calls. Add call 1: 'Product Search' — GET to /commerce/shopper-products/v1/organizations/{orgId}/product-search. Add parameters: orgId (static — your org ID), siteId (static — your site ID), q (search query text, dynamic), limit (results per page, default 25), offset (for pagination). To initialize, use a real access_token from your SFCCSession record and a search query that will return results. SCAPI product search nests results in a 'hits' array. Each hit contains: productId, productName, price, imageGroups, and other fields. Bubble will detect 'hits first item's productId', 'hits first item's productName', etc. Add call 2: 'Product Detail' — GET to /commerce/shopper-products/v1/organizations/{orgId}/products/{productId}. Parameters: orgId (static), siteId (static), productId (dynamic). The product detail response has a completely different schema from search hits: it uses 'id', 'name', 'longDescription', 'price', 'stepQuantity', and 'variants' (for variant products). Initialize this call separately with a specific product ID. Use the 'hits first item's productId' from a search result as the test value. Both calls require the accessToken group parameter — when initializing, paste the current token from your SFCCSession record into the accessToken parameter field. Build a product search page in Bubble: add a Search Input element, wire its value to the 'q' parameter of a Product Search API call, display results in a Repeating Group, and implement product detail navigation using the productId from search hits.
1// SCAPI Product Search response structure (partial)2{3 "limit": 25,4 "hits": [5 {6 "productId": "25592581M",7 "productName": "Striped Silk Tie",8 "price": 68.00,9 "priceMax": 78.00,10 "currency": "USD",11 "representedProduct": { "id": "25592581M" },12 "imageGroups": [13 {14 "viewType": "large",15 "images": [16 { "alt": "Silk Tie", "link": "https://...image.jpg", "title": "Silk Tie" }17 ]18 }19 ]20 }21 ],22 "offset": 0,23 "total": 4724}2526// SCAPI Product Detail response structure (DIFFERENT schema from search hits)27{28 "id": "25592581M",29 "name": "Striped Silk Tie",30 "longDescription": "<p>Premium Italian silk...</p>",31 "price": 68.00,32 "currency": "USD",33 "variants": [34 { "productId": "25592581M-RED", "price": 68.00, "orderable": true, "variationValues": { "color": "RED" } }35 ],36 "imageGroups": [ ... ]37}3839// Note: product search uses 'productId' and 'productName' (camelCase)40// Product detail uses 'id' and 'name' — different field names for the same conceptsPro tip: SCAPI product search uses 'productId' and 'productName' as field names, while product detail uses 'id' and 'name'. These different schemas for the same concept require two separate Bubble API Connector call definitions — you cannot use the same initialized call for both search results and detail pages.
Expected result: Two SCAPI calls are initialized in the SFCCShop group: Product Search (returning hits array) and Product Detail (returning a single product object with id, name, longDescription, variants). Product search results display in a Bubble Repeating Group and clicking a product navigates to a detail view.
Implement Basket Management and Proactive Token Refresh
SCAPI basket management (cart) uses a separate API path. Add a third call group or additional calls to SFCCShop for basket operations: POST to /commerce/shopper-baskets/v1/organizations/{orgId}/baskets to create a basket. The POST response returns a basket object with an 'basketId' (a UUID). Store this basketId in a Bubble data type — name it 'SFCCBasket' with fields: basket_id (text), user (User), created_date (date). All subsequent basket operations (add item: POST to /baskets/{basketId}/items; remove item: DELETE to /baskets/{basketId}/items/{itemId}; get basket: GET /baskets/{basketId}) use this stored basket ID. Create a Backend Workflow 'SFCC_CreateBasket' that calls the Create Basket API action, then creates an SFCCBasket record with the returned basketId. On page load of your storefront, check if the current user has an SFCCBasket record. If not, trigger SFCC_CreateBasket. For the token refresh, confirm your Recurring Backend Workflow is active (check Settings → Backend Workflows in Bubble's editor). You can test it by manually editing an SFCCSession record to set token_expiry to 2 minutes from now — within 25 minutes, the Recurring Workflow should refresh it. In Bubble's Logs tab, look for the workflow execution records to confirm it ran. Finally, important context for any team considering this integration at scale: this architecture (proxy function + token management + basket state) represents a significant investment in infrastructure before a single shopper interacts with your store. If your team needs guidance designing this for a production deployment, RapidDev has hands-on experience with enterprise API integrations in Bubble — reach out at rapidevelopers.com/contact for a scoping conversation.
1// SCAPI Create Basket — POST to /baskets2// Returns a basket object with basketId (use this for all subsequent cart operations)34// POST /commerce/shopper-baskets/v1/organizations/{orgId}/baskets5// Headers: Authorization: Bearer {accessToken} (from SFCCSession)6// Body: {} (empty JSON object for guest basket)78// Expected response (partial):9{10 "basketId": "bd2c4e0e9f9c4ce7826ab8c5e3af1a90",11 "currency": "USD",12 "productItems": [],13 "creationDate": "2024-01-15T10:30:00.000Z",14 "lastModified": "2024-01-15T10:30:00.000Z",15 "orderTotal": 0.0016}1718// Store basketId in SFCCBasket data type:19// basket_id = bd2c4e0e9f9c4ce7826ab8c5e3af1a9020// user = Current User21// created_date = Current date/time2223// Add to cart — POST /baskets/{basketId}/items24// Body:25{26 "productId": "<productId dynamic>",27 "quantity": 128}Pro tip: SLAS guest tokens are tied to a shopper session, not a basket. If a token refresh happens between when a basket was created and when the user adds an item, the new token should still be able to access the existing basket — but verify this in your SFCC org's SLAS configuration, as some orgs configure guest sessions differently.
Expected result: Adding an item to the cart triggers the Backend Workflow, which uses the stored basketId and current access_token to call SCAPI. The basket item is added successfully. The Recurring Backend Workflow for token refresh shows execution records in Bubble's Logs tab every 25 minutes.
Common use cases
Headless Shopper Storefront
Build a custom-designed product browsing and shopping experience in Bubble that uses SFCC as the commerce backend. Fetch product catalog data from SCAPI, display it with custom Bubble layouts, manage shopper baskets through the baskets API, and redirect to SFCC's native checkout. This approach gives brands full control over the browsing UX while keeping SFCC's order management, inventory, and pricing logic intact.
Show all products in the 'Women's Outerwear' category from SFCC sorted by relevance, with color swatches, pricing, and availability — in my brand's custom Bubble design.
Copy this prompt to try it in Bubble
SFCC Order Lookup Tool for Support Teams
Build an internal Bubble app for customer support agents to look up SFCC orders, view order history, check order status, and find customer account information. Uses SCAPI's shopper orders and customers endpoints with a service-user token (rather than per-customer guest tokens) so support staff can search any customer without individual OAuth authorization flows.
Look up all SFCC orders for customer email 'john.doe@brand.com' from the last 90 days, showing order number, status, items, and shipping tracking.
Copy this prompt to try it in Bubble
Product and Inventory Dashboard
Create a Bubble-based monitoring dashboard for merchandise managers to view SFCC product availability, pricing, and promotion status across sites and channels. Uses SCAPI product-search to surface inventory alerts and pricing discrepancies, with read-only access for stakeholders who should not have full SFCC Business Manager access.
Show all SFCC products with inventory below 10 units across all color/size variants, grouped by category, with direct links to the SFCC Business Manager product record.
Copy this prompt to try it in Bubble
Troubleshooting
Network error or HTTP 404 when calling SCAPI endpoints — not a 401
Cause: The shortcode in your SCAPI base URL is wrong. An incorrect shortcode produces a connection error or 404 rather than an authentication error because Salesforce routes requests based on the shortcode before evaluating credentials.
Solution: Log into Salesforce Business Manager and confirm your exact shortcode. The shortcode appears in the SCAPI base URL format: https://{shortcode}.api.commercecloud.salesforce.com. Verify it is alphanumeric only, no spaces or special characters. Update the SFCCShop API Connector group root URL with the correct shortcode and re-initialize all calls.
HTTP 401 on SCAPI calls after the app has been running for 30+ minutes
Cause: The SLAS access token expired (typically after ~30 minutes) and the Recurring Backend Workflow did not refresh it in time, or the refresh failed silently.
Solution: Check Bubble's Logs tab for the SFCC_RefreshSession workflow — look for execution failures. Common failure causes: the stored refresh_token in the SFCCSession record is stale (if a previous refresh saved the wrong field), the Cloud Function endpoint is unreachable, or the Recurring Backend Workflow is not active. Re-run SFCC_InitSession to get a fresh token pair and confirm the Recurring Workflow is scheduled.
Firebase Cloud Function returns 500 error or fails to mint SLAS token
Cause: SLAS credentials in the Firebase function config are incorrect (wrong client_id, org_id, or shortcode), the SLAS API client is not configured in Business Manager, or the Firebase function has not been deployed with the latest code.
Solution: Test the SLAS token endpoint directly using curl or Postman with your credentials to confirm they are valid before investigating the Firebase function. Verify that firebase functions:config:get shows the correct sfcc configuration values. Redeploy the function with firebase deploy --only functions and check the Firebase console logs for the specific error message from the SLAS endpoint.
'There was an issue setting up your call' during SCAPI API Connector initialization
Cause: The access_token used during initialization is expired, the SFCC site ID in the endpoint path is wrong, or the org_id parameter does not match a valid organization.
Solution: Run the SFCC_InitSession Backend Workflow to get a fresh access_token, copy the value from the SFCCSession record in Bubble's database, and use it as the accessToken parameter during initialization. Verify the orgId and siteId parameter values match exactly what is in Business Manager — site IDs are case-sensitive in SCAPI.
SCAPI product search fields look different from product detail fields for the same product
Cause: SCAPI product search (the /product-search endpoint) and product detail (the /products/{id} endpoint) intentionally use different JSON schemas. Search returns 'productId' and 'productName'; detail returns 'id' and 'name'. These are not the same Bubble API call.
Solution: Initialize each endpoint separately in the API Connector as two distinct calls. Use the search call's 'hits' array to build listing pages; use the detail call's 'id' and 'name' fields for product detail pages. Never try to use the same initialized call for both contexts — Bubble's detected fields will conflict.
Best practices
- Deploy and test the Firebase Cloud Function (or Cloudflare Worker) completely before attempting any Bubble API Connector setup. A working, independently testable proxy removes auth complexity as a variable when debugging Bubble configuration.
- Store SLAS credentials exclusively in Firebase function config or environment variables — never in Bubble's database, API Connector headers, or any client-accessible location. The proxy function exists specifically to keep these credentials isolated.
- Set up the Recurring Backend Workflow for token refresh before building any commerce features. Token expiry at 30 minutes is aggressive — forgetting the refresh mechanism and building the UI first means you will hit 401 errors constantly during development.
- Create separate API Connector calls for SCAPI product search and product detail. They have different JSON schemas and cannot share a single initialized Bubble API call definition.
- Apply Bubble privacy rules to SFCCSession and SFCCBasket data types immediately. By default all Bubble users can read all records of a type — these token and basket records must be restricted to their owning user.
- Verify your SFCC org's SLAS token TTL in Business Manager before setting the Recurring Backend Workflow interval. If the TTL is shorter than 30 minutes, adjust the workflow to run more frequently — a conservative rule is to refresh at 75% of the TTL.
- Communicate upfront with stakeholders that SFCC requires an active enterprise contract, a deployed proxy function, and a paid Bubble plan. There is no path to a working demo without all three prerequisites in place.
- Use Bubble's Logs tab extensively during development — every Backend Workflow execution, every API call, and every error appears there. SCAPI returns detailed error messages including SLAS error codes that point to specific misconfiguration.
Alternatives
BigCommerce is a self-serve SaaS e-commerce platform with a static access token and straightforward API Connector setup — no proxy function, no PKCE OAuth, no enterprise contract required. Start at $39/month. If your project does not require SFCC specifically (e.g., you do not already have an SFCC implementation), BigCommerce provides headless commerce capabilities with a fraction of the integration complexity.
WooCommerce is open-source and self-hosted on WordPress, with consumer key and secret authentication. It is accessible to any developer with WordPress hosting, without enterprise contracts or complex OAuth proxy requirements. WooCommerce lacks SFCC's enterprise-grade merchandising, multi-site management, and B2B features, but integrates with Bubble in under an hour versus SFCC's multi-day setup.
Magento (Adobe Commerce) is open-source e-commerce that can be self-hosted or cloud-hosted and offers enterprise-scale customization comparable to SFCC. Its REST API uses OAuth 1.0a or Bearer tokens depending on the endpoint, with no SLAS proxy requirement. Magento's integration in Bubble is significantly simpler than SFCC while offering similar catalog depth. Consider Magento as an alternative when SFCC's enterprise pricing is prohibitive.
Frequently asked questions
Can I try this integration without an SFCC enterprise contract?
No. Salesforce Commerce Cloud does not offer a free tier, developer sandbox, or self-serve trial. API access requires an active enterprise contract or a sandbox environment provided through a Salesforce partner relationship. If you are evaluating whether to adopt SFCC, contact Salesforce directly for a demo environment or work through a certified Salesforce partner who can provide a sandbox for proof-of-concept work.
Why can't Bubble's API Connector handle the SLAS token minting directly?
Two reasons. First, SLAS requires PKCE (generating a code_verifier and computing its SHA-256 hash as a code_challenge) — Bubble cannot perform cryptographic operations natively in the API Connector or in Backend Workflows without the Toolbox plugin. Second, and more critically, SLAS client credentials (client_id and potentially client_secret) must never be exposed to any client-accessible context. Even with Bubble's Private header, placing SLAS credentials in the API Connector is insufficient security for enterprise credentials. A server-side proxy function (Firebase or Cloudflare) is the architecturally correct and required approach.
How long do SLAS tokens last and what happens when they expire?
SLAS guest tokens typically expire after approximately 30 minutes (1800 seconds), but the exact TTL is configurable per SFCC org in Business Manager under SLAS API Client settings. When a token expires, all SCAPI calls return HTTP 401. The Recurring Backend Workflow for token refresh (running every 25 minutes) prevents expiry by proactively refreshing tokens before they reach their TTL. If a token does expire mid-session, trigger SFCC_InitSession to get a fresh token pair — the user may need to re-start their basket if the session state was tied to the expired token.
Do I need a paid Bubble plan for this integration?
Yes, absolutely. This integration requires Backend Workflows for SLAS token management (called on page load), recurring token refresh (Recurring Backend Workflow), and basket operations. Backend Workflows and Recurring Backend Workflows are only available on paid Bubble plans. This integration cannot be built on Bubble's Free plan.
What is the difference between SCAPI and OCAPI in SFCC?
SCAPI (Salesforce Commerce API) is the current, modern API for SFCC using SLAS authentication — this is what this tutorial covers. OCAPI (Open Commerce API) is the legacy API system with different authentication (OAuth 2.0 with a different flow) and different endpoint structures. Salesforce is migrating customers to SCAPI. Do not mix SCAPI and OCAPI documentation — they have different endpoint paths, different schemas, and different authentication requirements. If your SFCC org documentation references OCAPI, ask your Salesforce partner about the migration timeline to SCAPI.
Why does the wrong shortcode produce a network error instead of an authentication error?
SFCC routes requests based on the shortcode in the base URL before any authentication evaluation occurs. If the shortcode does not match a known SFCC org, Salesforce's infrastructure simply does not have a server at that URL to respond with a meaningful error — you get a connection error or 404. Verify your shortcode in Business Manager under your org's API configuration before making any API calls.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation