# Magento

- Tool: FlutterFlow
- Difficulty: Intermediate
- Time required: 60 minutes
- Last updated: July 2026

## TL;DR

Connect FlutterFlow to Magento (Adobe Commerce) using the REST API at /rest/V1/ with an Integration Token sent as a Bearer header. The two things people get wrong: creating an Admin Token instead of an Integration Token (Integration tokens don't expire on session logout), and malforming the searchCriteria query syntax for pagination. Proxy write operations through a Firebase Cloud Function so your token never ships in the compiled app.

## Building a FlutterFlow App on Top of Magento's REST API

Magento and Adobe Commerce power some of the world's largest e-commerce operations, offering a feature-rich REST API at /rest/V1/ that covers the full commerce lifecycle: products, categories, inventory, orders, customers, shopping carts, invoices, and more. For FlutterFlow builders, this opens the door to a wide range of mobile and web apps — a B2B ordering portal for sales reps, a customer-facing catalog with real-time inventory, or an operations dashboard for warehouse teams. The API surface is large, so this guide focuses on the patterns you need to get started: Integration Token auth, product and order listings, and multi-store URL prefixes.

The most important setup distinction: use a Magento Integration (System → Extensions → Integrations) rather than an Admin Token. Admin tokens are scoped to a logged-in admin session and may expire or be invalidated. An Integration generates a long-lived Access Token that you configure once in FlutterFlow. The second common stumbling block is Magento's searchCriteria query syntax — listing products requires parameters like searchCriteria[pageSize]=20&searchCriteria[currentPage]=1 rather than a simple ?page= format. These are modeled as FlutterFlow API Call variables so they can be wired to pagination controls in the UI.

Magento Open Source is free and self-hosted. Adobe Commerce (the enterprise edition) is licensed — check current Adobe pricing for your scale. There is no enforced API rate limit in core Magento; your server's capacity and any installed caching or firewall rules are the practical constraint. The Integration Token authorizes catalog reads and order writes, so treat it like a password: for anything touching orders or customer data, route calls through a Firebase Cloud Function so the token never ships inside the compiled Flutter app.

## Before you start

- A Magento Open Source or Adobe Commerce installation accessible over HTTPS
- Administrator access to the Magento admin panel (System → Extensions → Integrations)
- A FlutterFlow project open in the browser — no local installation required
- A Firebase project on the Blaze plan if you plan to proxy write operations through Cloud Functions
- Familiarity with FlutterFlow's API Calls panel and basic JSON path notation

## Step-by-step guide

### 1. Create a Magento Integration and copy the Access Token

Log in to the Magento admin panel (typically yourdomain.com/admin). In the left navigation, go to System → Extensions → Integrations. Click the Add New Integration button in the top-right corner.

On the New Integration form, enter a Name (e.g. 'FlutterFlow App'), your current admin password in the Password field, and optionally a description. On the API tab within the form, select the resource access level. For most FlutterFlow apps, choose 'Custom' and check the specific resources your app needs: under Catalog, check Products and Categories for read access; under Sales, check Orders if your app displays order data. Do not grant more resource access than required.

Click Save. Magento will create the Integration in an Inactive state. In the Integrations list, find your new integration and click Activate in the Action column. Magento will show you the Integration's tokens — you need the Access Token (the long string labeled 'Access Token', not the Consumer Key or Consumer Secret). Copy it and store it securely. This is the value you will use as your Bearer token in FlutterFlow.

IMPORTANT: This Access Token never expires by default (unlike Admin Tokens which expire based on session settings). However, if you Reauthorize or Delete the Integration, the token is invalidated and you must update FlutterFlow with a new one.

**Expected result:** The Integration appears as 'Active' in the Integrations list. You have copied the Access Token (a long alphanumeric string) and stored it for use in the next step.

### 2. Create the FlutterFlow API Group targeting /rest/V1/

In FlutterFlow, open your project and click API Calls in the left navigation panel. Click + Add, then Create API Group. Name it 'Magento'. Set the Base URL to https://yourdomain.com/rest/V1 (replace yourdomain.com with your actual Magento domain — no trailing slash).

For multi-store Magento setups, your base URL may include a store code prefix: https://yourdomain.com/rest/{storeCode}/V1. For example, a store with code 'us_store' would use https://yourdomain.com/rest/us_store/V1. If you only have the default store, 'default' is always valid: https://yourdomain.com/rest/default/V1. You can make the store code a variable if your app needs to switch between stores dynamically.

Under Headers, click + Add Header. Set the key to Authorization and the value to Bearer {{magentoToken}}. Create a new FlutterFlow variable named magentoToken to hold the Integration Access Token value. In a production app, initialize this variable from your App State on startup. For testing purposes, you can temporarily enter the token value directly, but replace it with a variable reference before distributing the app.

Also add a Content-Type header with value application/json — Magento requires this for POST/PUT requests.

Verify the setup by clicking Test in the API Group panel. If the connection succeeds you will see a valid response from a test endpoint. Any 401 response at this stage means the token is wrong or the Integration was not Activated.

```
{
  "api_group": "Magento",
  "base_url": "https://yourdomain.com/rest/V1",
  "headers": {
    "Authorization": "Bearer {{magentoToken}}",
    "Content-Type": "application/json"
  }
}
```

**Expected result:** The 'Magento' API Group appears in FlutterFlow's API Calls panel with the Bearer authorization header configured. The Group shows the base URL https://yourdomain.com/rest/V1.

### 3. Add product and order GET calls with searchCriteria pagination

Within the Magento API Group, click + Add API Call. Name it 'Get Products'. Set the Method to GET and the endpoint path to /products. Magento requires searchCriteria parameters to list resources — you cannot call /products without them (it returns a 400 or an empty array on some versions).

In the Variables tab of this API Call, add two variables: pageSize (integer, default 20) and currentPage (integer, default 1). In the endpoint path, append the searchCriteria query string using FlutterFlow's variable notation: /products?searchCriteria[pageSize]={{pageSize}}&searchCriteria[currentPage]={{currentPage}}

This is the most important syntax difference from other APIs: Magento uses bracket notation in query parameters, not simple ?page= and ?per_page=. Each bracket parameter must be URL-encoded correctly — FlutterFlow handles this automatically when you use the Variables tab.

For filtering (e.g. only show in-stock products), you can add searchCriteria filter groups: &searchCriteria[filter_groups][0][filters][0][field]=status&searchCriteria[filter_groups][0][filters][0][value]=1&searchCriteria[filter_groups][0][filters][0][condition_type]=eq. Add these as fixed query parameters if they never change, or as variables if the user can toggle them.

In the Response & Test tab, click Test (with pageSize=5 and currentPage=1 to get a small sample). Paste the JSON response and click Generate JSON Paths. Key paths to capture: $.items[*].id, $.items[*].sku, $.items[*].name, $.items[*].price, $.items[*].extension_attributes.stock_item.qty, $.total_count.

Repeat for orders: add an API Call named 'Get Orders' with endpoint /orders?searchCriteria[pageSize]={{pageSize}}&searchCriteria[currentPage]={{currentPage}}. Generate JSON paths from a sample order response to capture $.items[*].increment_id, $.items[*].status, $.items[*].grand_total, $.items[*].customer_email.

```
{
  "get_products": {
    "method": "GET",
    "endpoint": "/products",
    "query_params": {
      "searchCriteria[pageSize]": "{{pageSize}}",
      "searchCriteria[currentPage]": "{{currentPage}}"
    },
    "variables": [
      { "name": "pageSize", "type": "integer", "default": 20 },
      { "name": "currentPage", "type": "integer", "default": 1 }
    ],
    "json_paths": [
      "$.items[*].id",
      "$.items[*].sku",
      "$.items[*].name",
      "$.items[*].price",
      "$.items[*].extension_attributes.stock_item.qty",
      "$.total_count"
    ]
  },
  "get_orders": {
    "method": "GET",
    "endpoint": "/orders",
    "query_params": {
      "searchCriteria[pageSize]": "{{pageSize}}",
      "searchCriteria[currentPage]": "{{currentPage}}"
    },
    "json_paths": [
      "$.items[*].increment_id",
      "$.items[*].status",
      "$.items[*].grand_total",
      "$.items[*].customer_email",
      "$.items[*].created_at"
    ]
  }
}
```

**Expected result:** The 'Get Products' API Call test returns a JSON response with an items array and total_count. FlutterFlow generates JSON Path fields for id, sku, name, and price. The 'Get Orders' call similarly returns items with increment_id and status fields ready to bind.

### 4. Bind product and order data to FlutterFlow ListViews with pagination

Now wire the API Calls to your FlutterFlow UI. Open the Products screen in your canvas. Add a ListView widget. Select it and open the Backend Query panel on the right side. Choose API Call as the data source, select Magento → Get Products, and set the pageSize to 20 and currentPage to your App State variable (defaulting to 1).

FlutterFlow will ask which JSON Path array to use as the list items — select the $.items path. Each ListView item now has access to the mapped fields: sku, name, price, and qty (stock). Add Text widgets for each: product name bound to $.items[*].name, price bound to $.items[*].price (format as currency), SKU bound to $.items[*].sku.

For pagination, add two Buttons below the ListView: 'Previous' and 'Next'. The Next button's action should increment the currentPage App State variable and refresh the backend query. The Previous button decrements it. Disable the Previous button when currentPage equals 1, and disable Next when you have reached the last page (compare currentPage * pageSize against total_count stored in App State).

For the Orders screen, the same pattern applies: ListView → Backend Query → Magento → Get Orders. Display increment_id (the order number like #000000123), status (processing, complete, pending), grand_total, and created_at date. Tapping an order row navigates to a detail screen that calls /orders/{{orderId}} with the selected increment_id to fetch full order line items, shipping address, and payment information.

For multi-store: if your app serves multiple Magento stores, add a store selector on the home screen that sets an App State variable storeCode. Reference this variable in the API Group base URL as https://yourdomain.com/rest/{{storeCode}}/V1 so all API Calls automatically use the selected store's data.

**Expected result:** The Products screen shows a paginated list of Magento products with names, prices, and stock quantities. The Next/Previous buttons work correctly. The Orders screen lists recent orders with their increment IDs and statuses. Tapping an order navigates to a detail screen.

### 5. Proxy order and customer write operations through a Firebase Cloud Function

The Magento Integration Token authorizes order creation, customer account modifications, and inventory updates. If this token were embedded in the FlutterFlow project, anyone who decompiled the app binary would have full API access to your Magento store. Route all write operations through a Firebase Cloud Function that holds the token in its server-side environment configuration.

In the Firebase console, navigate to your project → Functions. If you are on the Spark (free) plan, upgrade to Blaze — outbound network calls from Cloud Functions require the paid plan. Create a new function (using the console's inline editor or a local deployment) that receives a request from your FlutterFlow app, validates it optionally using Firebase Auth ID tokens, then calls the Magento REST API with the Integration Token stored in Firebase environment config.

The Cloud Function acts as a transparent proxy: your FlutterFlow app sends the order payload (customer ID, cart items, shipping info) as JSON in the request body, and the function forwards it to Magento's /rest/V1/orders endpoint using the Integration Token. The function returns Magento's response (new order increment ID, order status) back to FlutterFlow.

In FlutterFlow, create a new API Group named 'MagentoProxy' with the base URL of your deployed Cloud Function (e.g. https://us-central1-yourproject.cloudfunctions.net). Add a 'Create Order' API Call with method POST. In the checkout flow, wire this call to a 'Place Order' button action. Store the returned increment_id in App State and navigate to a confirmation screen.

For reads, the token risk is lower since an attacker can only read catalog data that may already be public. You may choose to leave GET calls client-side and only proxy POST/PUT/DELETE operations — this is a reasonable middle ground that simplifies the architecture while protecting sensitive write operations.

```
// Firebase Cloud Function: magentoCreateOrder
// Node.js 18 runtime
const functions = require('firebase-functions');
const fetch = require('node-fetch');

// Set env: firebase functions:config:set magento.token="YOUR_TOKEN" magento.url="https://yourdomain.com"
const MAGENTO_TOKEN = functions.config().magento.token;
const MAGENTO_URL = functions.config().magento.url;

exports.magentoCreateOrder = functions.https.onRequest(async (req, res) => {
  // Optional: Add CORS headers for web builds
  res.set('Access-Control-Allow-Origin', '*');
  res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
  res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');

  if (req.method === 'OPTIONS') {
    return res.status(204).send('');
  }

  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method Not Allowed' });
  }

  const orderPayload = req.body;

  try {
    const response = await fetch(
      `${MAGENTO_URL}/rest/V1/orders`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${MAGENTO_TOKEN}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(orderPayload),
      }
    );

    const data = await response.json();

    if (!response.ok) {
      console.error('Magento API error:', data);
      return res.status(response.status).json(data);
    }

    return res.status(200).json(data);
  } catch (err) {
    console.error('Cloud Function error:', err);
    return res.status(500).json({ error: 'Internal server error' });
  }
});
```

**Expected result:** The Firebase Cloud Function is deployed and accessible at its HTTPS endpoint. The FlutterFlow 'Create Order' API Call successfully posts order data to the function, which creates the order in Magento and returns the increment_id. The Magento Integration Token does not appear in any FlutterFlow API Call header or exported Dart code.

## Best practices

- Always use a Magento Integration Token (System → Extensions → Integrations) rather than an Admin Token — Integration Tokens are long-lived, not tied to an admin session, and can be scoped to specific API resources
- Scope the Integration to only the resources your app needs: a catalog browser needs only Catalog Read permissions; an order management app adds Sales Order Read; never grant all-access unless absolutely required
- Never hardcode the Integration Token in a FlutterFlow API Call header value — store it in FlutterFlow App State and initialize it securely, or proxy all API calls through a Firebase Cloud Function that holds the token in server-side environment config
- Always use the searchCriteria query parameter syntax for listing endpoints: /products?searchCriteria[pageSize]=20&searchCriteria[currentPage]=1 — unlike simpler APIs, Magento requires this structure and returns no data without it
- For multi-store Magento setups, make the storeCode a FlutterFlow App State variable and inject it into the API Group base URL path (/rest/{{storeCode}}/V1) so users can switch stores without separate API Groups
- Proxy all order and customer write operations through a Firebase Cloud Function — the Integration Token authorizes writes that could affect real customer orders and should never be present in compiled app code
- Cache the product catalog in Firestore or Supabase if your FlutterFlow app has many users; Magento's PHP-based API can be slow under concurrent load compared to dedicated caching layers like Varnish
- Use Magento's $.total_count response field to implement correct pagination — calculate total pages as ceil(total_count / pageSize) and disable navigation buttons at boundaries to prevent empty-page requests

## Use cases

### B2B sales rep ordering app

A mobile app for field sales representatives that lets them browse the Magento product catalog by category, check stock levels, and place orders on behalf of customers. The rep selects a customer account, builds a cart, and submits through a Firebase Cloud Function proxy that creates the order using the Integration Token server-side.

Prompt example:

```
Build a sales rep app that lets users search products by SKU or name from Magento, view price tiers, and create a new order for a selected customer ID by calling a backend API.
```

### Customer order tracking companion app

A mobile app that allows customers to log in and view their Magento order history, shipment tracking numbers, and order line items. Orders are fetched from /rest/V1/orders using the customer's ID as a searchCriteria filter, and order details are displayed in a scrollable detail screen.

Prompt example:

```
Create an order tracking app where customers enter their email, the app fetches their orders from Magento using searchCriteria filters, and displays order status, items, and shipment tracking for each order.
```

### Warehouse inventory dashboard

An internal tablet app for warehouse staff that displays current product inventory levels from Magento, highlights out-of-stock and low-stock items, and allows stock quantity adjustments through a proxy Cloud Function. Products are listed using searchCriteria pagination with filtering by stock status.

Prompt example:

```
Build a warehouse dashboard that fetches all products from Magento with their stock quantities using pagination, highlights items with quantity below 5, and has a button to record a stock adjustment via a backend function.
```

## Troubleshooting

### 401 Unauthorized on every Magento API Call despite copying the token correctly

Cause: The Magento Integration was created but not Activated, or the token was copied before activation. An inactive Integration generates tokens that return 401. Alternatively, an Admin Token was used instead of the Integration Token — Admin Tokens expire based on Magento session lifetime settings.

Solution: Go to Magento Admin → System → Extensions → Integrations. Check that the Integration shows 'Active' status. If it shows 'Inactive', click Activate in the Action dropdown. After activation, copy the Access Token from the reauthorization dialog and update the FlutterFlow variable with the new token value. If you used an Admin Token (obtained via POST /rest/V1/integration/admin/token), replace it with the long-lived Integration Access Token.

### GET /products returns an empty items array or 400 Bad Request instead of product data

Cause: The searchCriteria parameters are missing or malformed. Magento's product listing endpoint requires searchCriteria even for a basic all-products query — calling /products without any searchCriteria parameters returns either an error or an empty result on many Magento versions.

Solution: Verify the API Call URL in FlutterFlow includes the full searchCriteria syntax: /products?searchCriteria[pageSize]=20&searchCriteria[currentPage]=1. Use the Variables tab to bind these as FlutterFlow variables rather than hardcoding them. In the Test tab, set pageSize to 5 and currentPage to 1 and run the test. If you get a 400, check that the bracket notation is not being double-encoded by the FlutterFlow variable substitution.

### Multi-store app shows the wrong store's products — always returns data from the default store

Cause: The store code is missing from or wrong in the API URL path. When no store code is specified, Magento falls back to the 'default' store view, which may not match the store the user is browsing.

Solution: Make the store code part of the API Group base URL as a variable: set the base URL to https://yourdomain.com/rest/{{storeCode}}/V1 and add storeCode as a FlutterFlow App State variable. Initialize it to the correct store code on app startup (or from a store selector). Verify the store code matches exactly what is configured in Magento Admin → Stores → All Stores (the 'Code' column, not the 'Name').

### XMLHttpRequest error on web builds but mobile builds work correctly

Cause: CORS is not enabled on the Magento server for browser-based requests. Magento does not add CORS headers by default, so web browsers block the request while native mobile apps are unaffected.

Solution: On the Magento server, add CORS headers to the web server config (Apache .htaccess or Nginx server block) for the /rest/ path: add 'Access-Control-Allow-Origin: *' (or your specific domain) and 'Access-Control-Allow-Headers: Authorization, Content-Type'. Alternatively, route all API Calls through your Firebase Cloud Function, which can set CORS headers explicitly. The Cloud Function approach is recommended for production because it also keeps the Integration Token server-side.

### searchCriteria filter returns an empty array even though matching products exist

Cause: The filter field name, condition_type, or value syntax is wrong. Magento's filter syntax is verbose and a minor typo — for example, using 'equal' instead of 'eq' as the condition_type — returns an empty set without an error message.

Solution: Double-check the exact searchCriteria filter syntax: field names must match Magento's API attribute names exactly (e.g. 'status' not 'is_active', 'type_id' not 'type'), condition_type must be one of 'eq', 'neq', 'gt', 'lt', 'gteq', 'lteq', 'like', 'in', 'null'. Test filters by constructing the full URL in your browser with the Bearer token to confirm the syntax before adding it to FlutterFlow.

## Frequently asked questions

### What is the difference between a Magento Integration Token and an Admin Token?

An Admin Token is obtained by posting admin credentials to /rest/V1/integration/admin/token and expires based on your Magento session lifetime settings (often 4 hours). An Integration Token is generated through System → Extensions → Integrations, is long-lived (does not expire on session logout), and can be scoped to specific API resources. For FlutterFlow integrations, always use the Integration Token — it is more secure, more reliable, and does not require re-authentication.

### Why do I need to use searchCriteria parameters for product listings?

Magento's REST API requires searchCriteria parameters for collection endpoints like /products and /orders because the underlying PHP framework uses them to build the database query. Without these parameters, Magento either returns an error or defaults to an empty result set. The simplest valid query is ?searchCriteria[pageSize]=20&searchCriteria[currentPage]=1, which returns the first 20 items. In FlutterFlow, model these as integer variables so they can be connected to pagination buttons.

### Can I use the same FlutterFlow project for multiple Magento store views?

Yes. Magento's multi-store architecture allows different store views under the same API endpoint, differentiated by a store code prefix in the URL: /rest/{storeCode}/V1/products. In FlutterFlow, make the storeCode an App State variable, set it based on the user's selected region or language, and inject it into the API Group base URL. Use /rest/default/V1 as the fallback. All API Calls in the group will automatically use the active store code.

### Is it safe to call the Magento API directly from the FlutterFlow client without a proxy?

For read-only product catalog data using a narrowly-scoped Integration Token, the risk is relatively low — an attacker who extracts the token can only read public catalog information. However, any token that grants access to orders, customer data, or write operations must not be in client code. If your Integration Token has write permissions, route all calls through a Firebase Cloud Function. If you are unsure how to set up the proxy, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

### How do I get product images from the Magento REST API?

The basic product listing endpoint (/rest/V1/products with searchCriteria) does not include media gallery images in the response by default. To get product images, you need to call /rest/V1/products/{sku}/media for each product, which returns an array of media entries including the image file path. Prepend your store's base media URL (https://yourdomain.com/pub/media/catalog/product) to the file path to get a usable image URL. For list screens, consider fetching images lazily as the user scrolls to avoid making a media API call for every product upfront.

### Does Magento have rate limiting on the REST API?

Core Magento Open Source does not enforce API rate limits at the application level. However, your hosting environment, reverse proxy (Nginx/Apache), or any installed security extensions may impose request rate limits. Adobe Commerce (the enterprise version) may have additional throttling through the Adobe Commerce Cloud infrastructure. If your FlutterFlow app generates high traffic, consider adding a caching layer in your Firebase Cloud Function or using Magento's built-in full-page cache to reduce backend load.

---

Source: https://www.rapidevelopers.com/flutterflow-integrations/magento
© RapidDev — https://www.rapidevelopers.com/flutterflow-integrations/magento
