Set up custom API integrations in FlutterFlow using the API Manager in the left navigation panel. Create an API Group for each external service with a shared base URL and authentication headers. Within each group, define individual API Calls specifying the method, path, query parameters, and request body. Test calls in the browser, extract JSON paths from the response, and bind results to page widgets via Backend Queries or Action Flows.
FlutterFlow API Manager: complete guide from API Group to data binding
The FlutterFlow API Manager lets you connect your app to any REST API without writing HTTP client code. The system has two levels: API Groups (shared configuration for one service — base URL, authentication headers, shared variables) and API Calls (individual endpoints within a group — method, path, parameters, request body, response extraction). Once an API Call is tested and saved, you can use it in two ways: as a Backend Query on a page or widget (to load data when the screen opens) or inside an Action Flow (to call the API when a button is tapped). This tutorial walks through both patterns using a real-world example.
Prerequisites
- A FlutterFlow project (any plan)
- An API to integrate — this tutorial uses the OpenWeather API (free tier, no credit card required at openweathermap.org)
- The API's base URL, authentication method, and at least one endpoint to test
- Basic understanding of REST concepts (GET/POST, headers, JSON)
Step-by-step guide
Create an API Group with base URL and authentication
Create an API Group with base URL and authentication
In FlutterFlow, go to API Manager in the left navigation panel (the plug icon). Click Add API Group. Give it a descriptive name matching the service — for example, OpenWeather. Set the Base URL to https://api.openweathermap.org/data/2.5. For authentication, look at the API docs to determine the method. Options in FlutterFlow: No Auth (public APIs), API Key in header (add a header like Authorization: ApiKey YOUR_KEY), API Key as query parameter (add to the query params section with key appid and value [OPENWEATHER_KEY]), Bearer Token (header Authorization: Bearer [token]), or Basic Auth. For OpenWeather, use query parameter authentication: add appid with value [OPENWEATHER_KEY]. Store the actual API key in FlutterFlow Secrets — go to Settings → Secrets → Add Secret named OPENWEATHER_KEY and paste your key. Reference it in the API Group as [OPENWEATHER_KEY] — FlutterFlow automatically substitutes the secret value.
Expected result: The API Group is created with the base URL and authentication configured. No calls are defined yet.
Add an API Call with path and response extraction
Add an API Call with path and response extraction
Inside the OpenWeather API Group, click Add API Call. Name it getCurrentWeather. Set Method to GET. Set the API URL Path to /weather (appended to the base URL). Under Query Parameters, add city with a default value of London for testing. The full request URL becomes https://api.openweathermap.org/data/2.5/weather?city=London&appid=YOUR_KEY. Click the Test tab → Send Request. You should see a JSON response. FlutterFlow displays the response structure — expand the JSON tree to find the fields you need. Click the + icon next to each field you want to use as a binding source. Common fields to extract: main.temp (temperature), weather[0].description (condition text), weather[0].icon (icon code), wind.speed. Each extracted field becomes a named variable you can bind to widgets. Click Save API Call.
Expected result: The getCurrentWeather API Call returns a 200 response and the extracted fields (temp, description, icon, wind speed) appear as bindable variables.
Use variable substitution for dynamic values
Use variable substitution for dynamic values
API calls with hardcoded values (city=London) are only useful for testing. To make values dynamic, use FlutterFlow's variable substitution syntax: [variableName] in URL paths, query parameters, headers, and JSON request bodies. To parameterize the city: in the Query Parameters section, change the city value from London to [city]. When you use this API Call in an Action Flow or Backend Query, FlutterFlow will prompt you to bind [city] to a Page State variable, Widget State (a TextField's current value), or any other data source. For POST requests with a JSON body, use the same syntax: {"userId": "[userId]", "amount": [amount]}. Variables inside strings use quotes; number variables do not. Example body for a payment API: {"customerId": "[customerId]", "amount": [amount], "currency": "usd"}.
Expected result: The API Call shows [city] as a required variable input, ready to be bound to any data source when used in an Action Flow or Backend Query.
Load API data on page open with a Backend Query
Load API data on page open with a Backend Query
To display API data when a page loads, add a Backend Query to the page or to a specific widget. Open the page properties (click an empty area of the page canvas) → Backend Query tab → Add Query → API Call. Select your OpenWeather API Group and the getCurrentWeather API Call. For the [city] variable, select a binding source: Page Parameter (if city is passed via navigation), Page State (if the user typed it in a search field), or App State (a global setting). The query runs automatically when the page loads. The query results are now available as a data source for all widgets on the page — click any Text widget, go to the content field, click Set from Variable, and select your Backend Query result then the specific extracted field (main.temp, weather[0].description, etc.).
Expected result: The page displays current weather data loaded from the API on page open, with text widgets showing temperature, conditions, and wind speed from the extracted response fields.
Call an API from an Action Flow (button or event trigger)
Call an API from an Action Flow (button or event trigger)
Some API calls should fire in response to a user action rather than on page load — submitting a form, clicking Like, or tapping Send. In the Action Flow editor, add a Backend Call action, select your API Group and API Call. Bind the variable inputs to form field values or Page State. The action outputs the API response — use the Action Output variable in subsequent actions in the same flow. For example: call a create order API Call → if the response orderStatus equals 'confirmed', navigate to the OrderConfirmation page passing the orderIdFromResponse as a parameter. To access the response: in the next action, click the source binding for any field, choose Action Outputs → your API Call name → the extracted field you need.
Expected result: Tapping the Submit button calls the API, and the next action in the flow uses the response data to navigate to a confirmation screen or show a success message.
Complete working example
1API Manager Structure:23API Group: OpenWeather4├── Base URL: https://api.openweathermap.org/data/2.55├── Auth: Query Param6│ └── appid: [OPENWEATHER_KEY] (stored in Settings → Secrets)7│8└── API Calls:9 ├── getCurrentWeather10 │ ├── Method: GET11 │ ├── Path: /weather12 │ ├── Query Params: city=[city]13 │ └── Extracted fields:14 │ ├── temp → main.temp (Number)15 │ ├── feelsLike → main.feels_like (Number)16 │ ├── description → weather[0].description (String)17 │ ├── iconCode → weather[0].icon (String)18 │ └── windSpeed → wind.speed (Number)19 │20 └── getForecast21 ├── Method: GET22 ├── Path: /forecast23 ├── Query Params: city=[city], cnt=524 └── Extracted fields:25 └── forecastList → list (List of JSON)2627Usage Pattern 1: Backend Query on Page28 Page → Properties → Backend Query → API Call29 → Bind [city] to: Page State.searchCity30 → Widget bindings: Text.content → Backend Query.temp3132Usage Pattern 2: Action Flow (button)33 Button OnTap → Action Flow:34 1. Backend Call: getCurrentWeather35 └── [city] = TextField.currentValue36 2. Conditional: if responseCode != 20037 └── Show Snackbar: 'City not found'38 3. Update Page State: currentTemp = ActionOutput.temp39 4. Navigate: WeatherDetailPage4041Secret reference syntax:42 In header value or param value: [SECRET_NAME]43 In JSON body: {"key": "[SECRET_NAME]"}44 FlutterFlow substitutes the actual value at runtime.Common mistakes
Why it's a problem: Hardcoding API keys directly in the API Group headers or query parameters
How to avoid: Store all API keys in Settings → Secrets. Reference them in the API Group as [SECRET_NAME]. The secret values are encrypted and not visible in the project editor or the compiled binary.
Why it's a problem: Creating a separate API Group for each endpoint instead of one group per service
How to avoid: Create one API Group per service with the base URL set at the group level. All API Calls in the group inherit the base URL. Changing from test.api.example.com to api.example.com requires changing one field in one group.
Why it's a problem: Not adding error handling after API Call actions in Action Flows
How to avoid: After every Backend Call action in an Action Flow, add a Conditional action: if the response code is not 200 (or not between 200-299), show a Snackbar with an error message. For critical flows (payments, form submission), also log the error to Firestore for debugging.
Best practices
- Use the Test tab in the API Call editor before binding to UI — verify the response structure matches your expectations before spending time on widget bindings that may not work
- Name API Groups after the service (OpenWeather, Stripe, MyBackend) and API Calls after the operation (getCurrentWeather, createPaymentIntent) — avoid generic names like Call1 or APIRequest
- For APIs that require OAuth tokens that expire, route the call through a Cloud Function that handles token refresh rather than embedding expiring tokens in the FlutterFlow API Group
- Test API Calls with realistic data including edge cases: empty responses, special characters in strings, very long text values — bindings that work for happy path data often fail on real-world inputs
- Use widget-level Backend Queries for independent sections of the page rather than loading all data at the page level — this allows parts of the page to load and display while others are still fetching
- For APIs that return paginated lists, design your UI to support cursor-based or page-based pagination from the start — retrofitting pagination into a list that initially loaded all data is significantly harder
- Document your API Groups with a naming convention and add descriptions in the group and call names — future collaborators (or yourself in 6 months) will thank you
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am setting up a custom API integration in FlutterFlow using the API Manager. I want to connect to the OpenWeather API to show current weather by city name. Explain: (1) how to structure the API Group with the base URL and API key as a query parameter, (2) how to create a getCurrentWeather API Call that accepts a city name as a variable, (3) which JSON fields to extract from the weather response for temperature, condition, and wind speed, and (4) how to bind the results to a FlutterFlow page using a Backend Query.
In my FlutterFlow project, create an API Group called OpenWeather with base URL https://api.openweathermap.org/data/2.5 and the appid authentication as a query parameter. Add an API Call named getCurrentWeather using GET /weather with a [city] query parameter. Extract the fields main.temp, weather[0].description, and wind.speed from the response. Show me how to bind these to three Text widgets on a weather page.
Frequently asked questions
Can FlutterFlow API Manager connect to GraphQL APIs?
Yes, but with limitations. GraphQL APIs use POST requests with a JSON body containing a 'query' string. In the API Call editor, set the method to POST and add the GraphQL query as a JSON body field: {"query": "{ products { id name price } }"}. FlutterFlow treats GraphQL calls like any other POST API call. The main limitation is that FlutterFlow cannot auto-introspect GraphQL schemas — you need to manually write the query string and extract the response fields. For complex GraphQL operations with variables, use the variable substitution syntax in the query body.
How do I handle API authentication that requires a login step first?
Two-step auth (login first, then use the token) requires an Action Flow: (1) call the login API Call with username and password, (2) extract the returned token from the response, (3) store it in App State or a Secure Storage Custom Action. Then in all subsequent API Calls, include the token in the header as Authorization: Bearer [userToken] where [userToken] is bound to the App State variable. For tokens that expire, add a token refresh step before protected API calls.
Why does my API Call work in the Test tab but fail when running the app?
The most common causes are: (1) variable substitution — the test uses the default value you set, but the live call passes an empty or incorrectly formatted value; (2) CORS — the API allows your test calls from the FlutterFlow domain but blocks calls from the mobile app (less common but happens with some corporate APIs); (3) environment differences — the test tab runs in the FlutterFlow browser environment, while the app runs as a native binary. Check that your variable bindings are correctly set and not passing null values.
What is the difference between a Backend Query and a Backend Call in an Action Flow?
A Backend Query runs when a page or widget loads and keeps data in sync if using real-time mode. It feeds data to the widgets in its scope via the binding menu. A Backend Call in an Action Flow runs when triggered by a user action (button tap, form submit) or automated event. Backend Calls are for writes and triggered reads; Backend Queries are for page load data. Use Backend Queries for displaying data and Backend Calls for modifying data.
Can I use FlutterFlow API Manager for my own backend API?
Yes — the API Manager works with any REST API including your own. If you have a Node.js, Python, or PHP backend, create an API Group pointing to your backend URL and add API Calls for each endpoint. This is the recommended pattern for custom backends that are not Firebase — your backend handles business logic and database operations, while FlutterFlow handles the UI and calls your backend endpoints via the API Manager.
What if my API integration is more complex than the standard FlutterFlow API Manager supports?
For APIs requiring request signing (AWS Signature V4), multipart file uploads, streaming responses, or complex OAuth flows, the API Manager reaches its limits. In those cases, use a Custom Action for the specific API call — write Dart code using the http or dio package with full control over headers, body encoding, and response parsing. RapidDev has handled complex API integrations including SAP SOAP, AWS services, and proprietary enterprise APIs in FlutterFlow projects.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation