Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Integrate FlutterFlow with Machine Learning APIs for Advanced Features

Call machine learning APIs from FlutterFlow by routing all cloud ML calls (Google Cloud Vision, OpenAI, Hugging Face) through Cloud Functions that hold API keys securely and cache results in Firestore. For offline or privacy-sensitive features (text recognition, barcode scanning, face detection), use Google ML Kit packages directly in Custom Actions — these run entirely on-device without sending data to any server. Always resize images to max 1024px before sending to cloud vision APIs.

What you'll learn

  • How to call Google Cloud Vision API and OpenAI from FlutterFlow via Cloud Function proxies
  • How to use on-device ML Kit packages for text recognition and barcode scanning without internet
  • How to cache ML API results in Firestore to avoid re-processing identical inputs
  • Why ML API images must be resized before sending to reduce latency and cost by up to 80%
  • How to structure the ML result display in FlutterFlow for labels, confidence scores, and AI text responses
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate12 min read45-90 min depending on ML featureFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Call machine learning APIs from FlutterFlow by routing all cloud ML calls (Google Cloud Vision, OpenAI, Hugging Face) through Cloud Functions that hold API keys securely and cache results in Firestore. For offline or privacy-sensitive features (text recognition, barcode scanning, face detection), use Google ML Kit packages directly in Custom Actions — these run entirely on-device without sending data to any server. Always resize images to max 1024px before sending to cloud vision APIs.

Cloud vision, AI text generation, and on-device ML in one FlutterFlow integration guide

Machine learning features in FlutterFlow fall into two categories: cloud APIs and on-device models. Cloud APIs (Google Cloud Vision, OpenAI, Hugging Face) are powerful but require internet access, have per-call costs, and need API keys that must be kept secret. On-device ML (Google ML Kit) runs entirely on the user's device, works offline, is free to use, and never sends user data to external servers. This tutorial covers four ML integration patterns ranked by usefulness for FlutterFlow apps: on-device text recognition (OCR), Google Cloud Vision for image labeling, OpenAI for AI-powered text generation, and Hugging Face for custom model inference. All cloud patterns use the Cloud Function proxy approach for security.

Prerequisites

  • A Firebase project connected to FlutterFlow with Blaze plan enabled for Cloud Functions
  • A Google Cloud project with Vision API enabled (cloud.google.com/vision)
  • An OpenAI API key for GPT integration (platform.openai.com)
  • Basic understanding of FlutterFlow Custom Actions and Cloud Functions

Step-by-step guide

1

Add Google ML Kit for on-device text recognition (no API key needed)

For OCR (reading text from images), start with Google ML Kit which runs entirely on-device — free, offline-capable, and privacy-preserving. In FlutterFlow → Custom Code → Pubspec Dependencies, add google_mlkit_text_recognition (version ^0.13.0). For iOS: go to Settings → iOS Settings → Info.plist and verify the minimum iOS deployment target is 14.0 or higher (ML Kit requirement). Create a Custom Action named recognizeText that takes an imagePath String parameter. In the action: create a TextRecognizer using TextRecognizer(script: TextRecognitionScript.latin), create an InputImage from the file path using InputImage.fromFilePath(imagePath), call recognizer.processImage(inputImage), concatenate all recognized text blocks into a single string, call recognizer.close() to free resources, and return the text. Use this action after image_picker captures or selects an image.

recognize_text_action.dart
1import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
2
3Future<String> recognizeText(String imagePath) async {
4 final recognizer = TextRecognizer(script: TextRecognitionScript.latin);
5 final inputImage = InputImage.fromFilePath(imagePath);
6
7 try {
8 final recognized = await recognizer.processImage(inputImage);
9 final text = recognized.blocks
10 .map((b) => b.text)
11 .join('\n');
12 return text.isEmpty ? 'No text found in image' : text;
13 } finally {
14 recognizer.close();
15 }
16}

Expected result: Custom Action returns extracted text from any image on the device. Works offline, no API calls made.

2

Build a Cloud Function proxy for Google Cloud Vision API

Google Cloud Vision identifies objects, labels, faces, logos, text, landmarks, and explicit content in images. Create an HTTPS Cloud Function named analyzeImage. It receives a base64-encoded image string and a list of feature types. The function calls the Vision API at https://vision.googleapis.com/v1/images:annotate using a service account key (JSON key stored in Firebase Secret Manager as GOOGLE_VISION_KEY). Request body: {requests: [{image: {content: base64Image}, features: [{type: 'LABEL_DETECTION', maxResults: 10}, {type: 'OBJECT_LOCALIZATION', maxResults: 5}]}]}. Parse the response and return: a labels array (description + score), a objects array (name + score), and any detected text from TEXT_DETECTION. Before calling the API, check Firestore cache: hash the image (MD5 of first 100 chars of base64) and look up in ml_cache collection. If cached result is less than 24 hours old, return the cached result without calling the API.

analyze_image_function.js
1const functions = require('firebase-functions');
2const { defineSecret } = require('firebase-functions/params');
3const admin = require('firebase-admin');
4const axios = require('axios');
5const crypto = require('crypto');
6
7if (!admin.apps.length) admin.initializeApp();
8const visionKey = defineSecret('GOOGLE_VISION_KEY');
9
10exports.analyzeImage = functions
11 .runWith({ secrets: ['GOOGLE_VISION_KEY'], memory: '512MB' })
12 .https.onCall(async (data) => {
13 const { base64Image, features = ['LABEL_DETECTION'] } = data;
14 if (!base64Image) throw new functions.https.HttpsError('invalid-argument', 'Image required');
15
16 // Check cache
17 const hash = crypto.createHash('md5').update(base64Image.slice(0, 200)).digest('hex');
18 const db = admin.firestore();
19 const cached = await db.collection('ml_cache').doc(hash).get();
20 if (cached.exists) {
21 const data = cached.data();
22 const age = (Date.now() - data.cachedAt.toMillis()) / 1000 / 3600;
23 if (age < 24) return data.result;
24 }
25
26 const request = {
27 requests: [{
28 image: { content: base64Image },
29 features: features.map(f => ({ type: f, maxResults: 10 }))
30 }]
31 };
32 const { data: response } = await axios.post(
33 `https://vision.googleapis.com/v1/images:annotate?key=${visionKey.value()}`,
34 request
35 );
36
37 const result = response.responses[0];
38 const output = {
39 labels: result.labelAnnotations?.map(l => ({ name: l.description, score: l.score })) || [],
40 objects: result.localizedObjectAnnotations?.map(o => ({ name: o.name, score: o.score })) || [],
41 text: result.textAnnotations?.[0]?.description || ''
42 };
43
44 await db.collection('ml_cache').doc(hash).set({
45 result: output,
46 cachedAt: admin.firestore.FieldValue.serverTimestamp()
47 });
48
49 return output;
50 });

Expected result: Cloud Function returns labels, detected objects, and text for any image. Repeated requests for the same image return cached results without API calls.

3

Build an OpenAI GPT integration via Cloud Function

Create a Cloud Function named chatWithAI that accepts a messages array and systemPrompt. Store the OpenAI API key in Firebase Secret Manager as OPENAI_API_KEY. The function calls POST https://api.openai.com/v1/chat/completions with model: gpt-4o-mini (cost-effective for most use cases), temperature: 0.7, max_tokens: 500, and the messages array including the system message. Return the content of the first choice. In FlutterFlow, create an AI Chat page with: a ListView of messages bound to a Page State messages list, a TextField for user input, and a Send button. The Send button's action flow: add the user message to the messages list (for immediate display), call the chatWithAI Cloud Function with the updated messages, append the AI response to the messages list. Use a CircularProgressIndicator while the call is in progress by tracking isLoading in Page State.

Expected result: AI chat interface sends user messages to GPT-4o-mini via Cloud Function and displays responses in a chat-style ListView.

4

Resize images before sending to cloud ML APIs

High-resolution photos from modern smartphones (12MP+) are 4-8MB JPEG files. Sending these to Cloud Vision or other ML APIs takes 3-5 seconds for upload alone and costs more (Vision API charges per image, and larger images sometimes count as multiple units). The solution: resize images on-device before sending. Add the image package to Pubspec Dependencies (version ^4.1.3). Create a Custom Function named resizeImageForML that takes an imagePath String. Read the file, decode the image with decodeImage, resize to max 1024px on the longest side using copyResize with a null value for the other dimension (preserves aspect ratio), re-encode as JPEG at quality 85, write to a temporary file, and return the new file path. Call this Custom Function before converting to base64 for the ML API call.

resize_image_action.dart
1import 'package:image/image.dart' as img;
2import 'package:path_provider/path_provider.dart';
3import 'dart:io';
4
5Future<String> resizeImageForML(String imagePath) async {
6 final bytes = await File(imagePath).readAsBytes();
7 final original = img.decodeImage(bytes);
8 if (original == null) return imagePath;
9
10 final maxDim = 1024;
11 final resized = (original.width > original.height)
12 ? img.copyResize(original, width: maxDim)
13 : img.copyResize(original, height: maxDim);
14
15 final tmpDir = await getTemporaryDirectory();
16 final outPath = '${tmpDir.path}/ml_resized_${DateTime.now().millisecondsSinceEpoch}.jpg';
17 await File(outPath).writeAsBytes(img.encodeJpg(resized, quality: 85));
18 return outPath;
19}

Expected result: Images are resized to max 1024px before being sent to Vision API. Upload time drops from 3-5 seconds to under 500ms. API response is identical for most content types.

5

Display ML results in FlutterFlow with labels and confidence scores

After calling the analyzeImage Cloud Function, store the returned labels and objects arrays in Page State variables (List<JSON>). In FlutterFlow, add a Column below the analyzed image. Add a Text widget showing 'Detected in this image:'. Add a Wrap widget (for horizontal chip layout) with children generated dynamically from the labels Page State list. Each label is a Chip widget showing the label name and score as percentage (multiply score by 100, format to 1 decimal). Color the chip based on score: if score > 0.9, use green; if score > 0.7 use blue; else use gray. For OpenAI text responses, display in a styled Container with markdown-like formatting using the flutter_markdown Custom Widget if you want formatted text output.

Expected result: ML results display as colored confidence chips below the analyzed image. High-confidence labels appear in green, medium in blue, low in gray.

Complete working example

analyze_image_function.js
1// Cloud Function: Multi-ML API proxy
2const functions = require('firebase-functions');
3const axios = require('axios');
4
5// Google Cloud Vision - Image Analysis
6exports.analyzeImage = functions.https.onCall(async (data, context) => {
7 if (!context.auth) throw new functions.https.HttpsError('unauthenticated', 'Login required');
8
9 const visionRes = await axios.post(
10 `https://vision.googleapis.com/v1/images:annotate?key=${functions.config().google.vision_key}`,
11 { requests: [{ image: { content: data.imageBase64 },
12 features: [{ type: 'LABEL_DETECTION', maxResults: 10 },
13 { type: 'OBJECT_LOCALIZATION', maxResults: 5 },
14 { type: 'TEXT_DETECTION' }] }] }
15 );
16 return visionRes.data.responses[0];
17});
18
19// OpenAI Chat Completion - Text Generation
20exports.chatCompletion = functions.https.onCall(async (data, context) => {
21 if (!context.auth) throw new functions.https.HttpsError('unauthenticated', 'Login required');
22
23 const openaiRes = await axios.post(
24 'https://api.openai.com/v1/chat/completions',
25 { model: 'gpt-4o', messages: data.messages, max_tokens: data.maxTokens || 500 },
26 { headers: { Authorization: `Bearer ${functions.config().openai.api_key}` } }
27 );
28 return { message: openaiRes.data.choices[0].message.content };
29});
30
31// Hugging Face Inference - Custom Model
32exports.runInference = functions.https.onCall(async (data, context) => {
33 if (!context.auth) throw new functions.https.HttpsError('unauthenticated', 'Login required');
34
35 const hfRes = await axios.post(
36 `https://api-inference.huggingface.co/models/${data.modelId}`,
37 { inputs: data.inputs },
38 { headers: { Authorization: `Bearer ${functions.config().huggingface.token}` } }
39 );
40 return hfRes.data;
41});

Common mistakes

Why it's a problem: Sending raw high-resolution smartphone images (4-8MB) to cloud ML APIs without resizing first

How to avoid: Resize images to max 1024px on the longest side before converting to base64 and sending to any ML API. Use the image package in a Custom Action as shown in Step 4. This reduces upload time from 3-5 seconds to under 500ms with identical classification accuracy.

Why it's a problem: Calling cloud ML APIs (Vision, OpenAI) directly from FlutterFlow's API Manager without a Cloud Function proxy

How to avoid: All cloud ML API calls must go through Cloud Functions that read API keys from Firebase Secret Manager at runtime. FlutterFlow calls your Cloud Function (which has no key in client code). The Cloud Function calls the ML API with the secret key added server-side.

Why it's a problem: Not caching ML API results for identical inputs, calling the API repeatedly for the same content

How to avoid: Before calling any cloud ML API, hash the input (image base64 prefix or text prompt) and check a Firestore ml_cache collection for a recent result. If found and under 24 hours old, return the cached result. Only call the ML API on cache misses. This typically reduces ML API costs by 60-80% for apps with repeated content.

Best practices

  • Use on-device ML Kit for any feature that can work offline — text recognition, barcode scanning, face detection, and pose estimation are all available on-device with zero API cost and better user privacy
  • Add a loading state (CircularProgressIndicator) whenever triggering an ML API call — cloud ML calls take 500ms-3 seconds, and users need visual feedback that something is happening
  • Set explicit max_tokens limits on OpenAI calls to control cost — a 1,000-token limit on GPT-4o-mini costs about $0.00015 per call, while an uncapped call can run much longer
  • For image classification features, show confidence scores as percentages alongside labels — a 95% confidence label should be displayed differently than a 45% label to help users understand reliability
  • Add explicit content filtering for user-submitted images before displaying in your app — Google Vision's SAFE_SEARCH_DETECTION feature returns adult, violence, and medical content ratings that you can use to block inappropriate uploads
  • Cache on-device ML Kit model downloads — on first use, ML Kit downloads language models (200-500MB). Show a 'Downloading language model' progress indicator on first run so users are not surprised by the delay

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a FlutterFlow app with AI features. Write me: (1) A Firebase Cloud Function that calls the Google Cloud Vision API to analyze an image and returns labels with confidence scores, with Firestore caching to avoid re-processing identical images, (2) A second Cloud Function that calls OpenAI GPT-4o-mini for AI chat responses, and (3) A Flutter Custom Action using google_mlkit_text_recognition for on-device OCR that works offline. Include the image resizing step before the Vision API call.

FlutterFlow Prompt

Add an image analysis feature to my FlutterFlow app. After the user picks an image with image_picker, resize it to 1024px using a Custom Action, convert to base64, call the analyzeImage Cloud Function, and display the returned labels as colored chips below the image. Show green chips for confidence > 90%, blue for > 70%, gray for lower confidence.

Frequently asked questions

What is the cheapest way to add AI features to a FlutterFlow app?

Start with Google ML Kit for any features that can work on-device (OCR, barcode scanning, face detection, pose estimation) — it is completely free and requires no Cloud Function. For cloud AI, GPT-4o-mini via OpenAI ($0.15/$0.60 per million input/output tokens) is the most cost-effective LLM for chat and text generation. Google Cloud Vision Label Detection costs $1.50 per 1,000 images. Adding Firestore caching to your Cloud Functions typically reduces actual API costs by 60-80% for apps where users analyze similar content.

Can I use Hugging Face models instead of OpenAI in FlutterFlow?

Yes. Hugging Face Inference API supports thousands of models including image classification, sentiment analysis, translation, and text generation. The endpoint format is https://api-inference.huggingface.co/models/{model-name} with an Authorization: Bearer header. Route through a Cloud Function with the Hugging Face API token stored in Secret Manager. Many Hugging Face models are free on the shared inference tier, with paid plans for higher throughput.

How do I prevent excessive OpenAI costs from my FlutterFlow app?

Three controls: (1) Set max_tokens in every OpenAI API call — 300-500 tokens is sufficient for most chat responses. (2) Add a rate limit in your Cloud Function: store user_id + timestamp in Firestore and reject calls if a user has made more than 10 requests in the last minute. (3) Add Firestore caching for identical prompts — if two users ask the same question, serve the cached response to the second user. Monitor costs daily in the OpenAI dashboard and set a spending limit alert.

Does Google ML Kit work on all Android and iOS devices?

Google ML Kit works on Android 5.0 (API 21) and above, and iOS 14 and above. Some ML Kit features download model files on first use — ensure the device has an internet connection for this initial download. After downloading, features work offline. For performance: ML Kit runs fastest on devices with a Neural Engine (iPhone 8+, iOS) or on-device NPU (newer Android flagships). Older mid-range Android devices run ML Kit features more slowly.

Can FlutterFlow use on-device large language models (LLMs) like Gemini Nano?

On-device LLMs are becoming available on newer devices. Google's Gemini Nano is available on Pixel 8+ and some Samsung Galaxy devices via the Android AICore API. Apple's on-device LLM features require iOS 18+. Neither has a stable Flutter package as of March 2026 for use in FlutterFlow. For now, small on-device language models via the llama.cpp Flutter package exist but are experimental. Check pub.dev for on_device_llm or flutter_llama for the current status.

Can RapidDev help build AI-powered features in my FlutterFlow app?

Yes. AI features that combine multiple ML APIs (Vision + OpenAI for describe-this-image, OCR + NLP for document extraction, image search using embeddings) require both ML API expertise and FlutterFlow architecture knowledge. RapidDev has built AI document processors, image classifiers, AI chat assistants, and smart recommendation systems for FlutterFlow apps across healthcare, legal, retail, and education verticals.

RapidDev

Talk to an Expert

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

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

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.