Connect FlutterFlow to Google Cloud AI Platform (Vertex AI) using a FlutterFlow API Group pointed at a Cloud Function proxy that mints a short-lived Google OAuth access token from your service account and forwards prediction requests to the Vertex AI REST endpoint at REGION-aiplatform.googleapis.com/v1. The service-account private key must never leave the Cloud Function — it grants project-wide Google Cloud access and cannot ship in a compiled Flutter app.
| Fact | Value |
|---|---|
| Tool | Google Cloud AI Platform |
| Category | AI & ML |
| Method | FlutterFlow API Call |
| Difficulty | Advanced |
| Time required | 60 minutes |
| Last updated | July 2026 |
Vertex AI in FlutterFlow: The Service-Account Proxy Pattern
Google Cloud AI Platform — rebranded as Vertex AI in 2021 — lets you deploy custom ML models and call them via a REST prediction API. Each deployed model has an endpoint URL in the format `https://REGION-aiplatform.googleapis.com/v1/projects/{project}/locations/{region}/endpoints/{endpoint}:predict`. The region must match exactly where your endpoint was deployed, and the request needs a valid OAuth 2.0 Bearer access token in the Authorization header.
Here is the security problem that makes this more complex than a simple API Call: Vertex AI uses Google service accounts for authentication. A service account has a JSON key file that contains a private RSA key. You use that private key to sign a JWT, which you exchange for a short-lived access token at `https://oauth2.googleapis.com/token`. That access token is valid for about one hour and is what goes in the Authorization header. The service-account JSON key grants access to every Google Cloud resource the service account can reach — putting it in a FlutterFlow App Constant or API Call header would embed it in your compiled APK, where it could be extracted and used to access your entire Google Cloud project.
The correct architecture is a Cloud Function proxy: the function holds the service-account JSON in its environment configuration, mints a fresh access token for each prediction request, and forwards the request to Vertex AI. FlutterFlow's API Group calls your Cloud Function URL, not Google's API directly. This pattern also solves the CORS problem for web builds, because the Cloud Function adds the correct response headers while making the outbound call to Google server-to-server.
Integration method
FlutterFlow's API Group sends prediction requests to a Cloud Function proxy, which holds the Google service-account private key, mints a short-lived OAuth 2.0 access token from oauth2.googleapis.com/token, and forwards the :predict call to the correct Vertex AI regional endpoint. This two-layer architecture keeps the service-account JSON — which grants project-wide Google Cloud access — off the compiled Flutter client. The API Group itself requires no authentication headers because the Cloud Function handles all token logic server-side.
Prerequisites
- A Google Cloud project with Vertex AI API enabled and at least one deployed model endpoint
- A Google Cloud service account with the 'Vertex AI User' IAM role, and its JSON key downloaded
- A Firebase project with Cloud Functions enabled (Blaze plan required for outbound network calls)
- A FlutterFlow project on a paid plan (API Calls are available on all paid tiers)
- Basic familiarity with Cloud Functions deployment (firebase deploy --only functions) and the Google Cloud Console
Step-by-step guide
Deploy a Vertex AI endpoint and note the project, region, and endpoint ID
Before writing any FlutterFlow configuration, you need a deployed Vertex AI endpoint to call. Open the Google Cloud Console (console.cloud.google.com) and navigate to Vertex AI → Online Prediction → Endpoints. If you already have a deployed model, click on it and note three values from the endpoint details page: the Project ID (visible in the top-left project selector), the Region (e.g. us-central1), and the Endpoint ID (a long numeric string shown in the endpoint details). If you do not have a model deployed yet, you can either upload a pre-built TensorFlow SavedModel to the Vertex AI Model Registry (Vertex AI → Model Registry → Import) and deploy it to a new endpoint, or use one of Google's pre-trained AutoML models. For testing purposes, Vertex AI also offers the Gemini API via the same auth pattern, but that uses a different endpoint URL structure. The prediction endpoint URL you will eventually call from the Cloud Function follows this exact pattern: `https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:predict`. Write down all three values — a typo in the region causes a 404 that is difficult to diagnose because the error message from Google is generic. Also note whether your model expects a `instances` array of objects or an `instances` array of arrays (depending on how the model was trained). Check the endpoint's 'Sample request' tab in the Cloud Console to see the exact input format your model expects.
Pro tip: Test the endpoint directly in the Cloud Console using the 'Test your model' panel before building the proxy. This confirms the model is serving and shows you exactly what the predictions array looks like.
Expected result: You have a deployed Vertex AI endpoint and have noted the project ID, region, and endpoint ID. You know the exact input format your model expects in the instances array.
Create a service account and deploy the Cloud Function proxy
In the Google Cloud Console, navigate to IAM & Admin → Service Accounts. Click 'Create Service Account', give it a name like 'vertexai-proxy', and on step 2 assign the 'Vertex AI User' role. After creating the account, click the three-dot menu on its row and select 'Manage Keys'. Click 'Add Key → Create new key → JSON'. Download the JSON file — this file contains the private key that will live in your Cloud Function. Now open your Firebase project's functions directory (or create a new Cloud Functions project). The proxy function needs the `google-auth-library` npm package, which handles JWT signing and token exchange automatically without you manually building the token request. In your package.json, add `"google-auth-library": "^9.0.0"` to dependencies. The function reads the service-account JSON from an environment variable (never hardcode it), uses the `GoogleAuth` class to obtain a short-lived access token scoped to `https://www.googleapis.com/auth/cloud-platform`, then POSTs the `{instances: [...]}` body to the Vertex AI :predict URL with the token in the Authorization header. The function returns the raw Vertex AI response to FlutterFlow. Deploy the function, then test it by POSTing a sample instance to the function URL using a tool like Postman or curl. Confirm that the function returns a predictions array before moving to FlutterFlow. Store the service-account JSON in Firebase Secret Manager rather than as a plain environment variable for production use.
1// Cloud Function: Vertex AI proxy2const functions = require('firebase-functions');3const { GoogleAuth } = require('google-auth-library');4const fetch = require('node-fetch');56const PROJECT_ID = process.env.GCP_PROJECT_ID;7const REGION = process.env.VERTEX_REGION; // e.g. 'us-central1'8const ENDPOINT_ID = process.env.VERTEX_ENDPOINT; // numeric endpoint ID910// Service account JSON stored as an env var (base64-encoded in prod)11const SERVICE_ACCOUNT_JSON = JSON.parse(12 Buffer.from(process.env.SERVICE_ACCOUNT_B64, 'base64').toString('utf8')13);1415exports.vertexPredict = functions.https.onRequest(async (req, res) => {16 res.set('Access-Control-Allow-Origin', '*');17 res.set('Access-Control-Allow-Headers', 'Content-Type');18 if (req.method === 'OPTIONS') { res.status(204).send(''); return; }1920 const { instances } = req.body;21 if (!instances) { res.status(400).json({ error: 'instances required' }); return; }2223 // Mint a short-lived access token24 const auth = new GoogleAuth({25 credentials: SERVICE_ACCOUNT_JSON,26 scopes: ['https://www.googleapis.com/auth/cloud-platform']27 });28 const client = await auth.getClient();29 const { token } = await client.getAccessToken();3031 const url = `https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${REGION}/endpoints/${ENDPOINT_ID}:predict`;3233 const vertexRes = await fetch(url, {34 method: 'POST',35 headers: {36 'Authorization': `Bearer ${token}`,37 'Content-Type': 'application/json'38 },39 body: JSON.stringify({ instances })40 });4142 const data = await vertexRes.json();43 res.status(vertexRes.status).json(data);44});Pro tip: Base64-encode the service-account JSON before storing it as an environment variable to avoid issues with newlines and special characters in the key fields: `base64 -i service-account.json | tr -d '\n'`
Expected result: The deployed Cloud Function returns a Vertex AI predictions JSON response when called with a sample instances body. The service-account JSON is stored in environment config, not in the function source code.
Create the Vertex AI API Group in FlutterFlow
With your Cloud Function proxy running and returning correct predictions, open your FlutterFlow project. Click API Calls in the left navigation panel, then click + Add and choose Create API Group. Name the group 'VertexAI' and set the Base URL to your Cloud Function's HTTPS URL (e.g. `https://us-central1-your-project.cloudfunctions.net/vertexPredict`). You do not need to add any headers to the group itself — all authentication is handled inside the Cloud Function. Next, add an API Call inside the group: click the + icon next to the group name and select Add API Call. Name it 'Predict' and set the method to POST. In the Variables tab, add a variable named `instances` of type String — you will pass a JSON string representation of your instances array from FlutterFlow (since FlutterFlow's API Call variable types are limited to primitive types, you will serialize the instances as a JSON string and parse it in the Cloud Function, or structure the body directly). In the Request Body tab, switch to JSON body type and enter the body as `{"instances": {{ instances }} }`. Note that for more complex input structures, you may need to define multiple individual variables and build the instances object in FlutterFlow's Action Flow Editor before passing it to the API Call. Go to the Response & Test tab. In the sample response field, paste a real Vertex AI response from your test earlier. Click Generate JSON Paths. FlutterFlow will parse the predictions array and generate paths like `$.predictions[0]` or deeper paths if your model returns structured objects. Name them clearly (e.g. `topLabel`, `confidence`, `forecastValue`) based on what your model returns. Save the API Group.
1// Sample Vertex AI API Call configuration2{3 "group_name": "VertexAI",4 "base_url": "https://us-central1-YOUR_PROJECT.cloudfunctions.net/vertexPredict",5 "calls": [6 {7 "name": "Predict",8 "method": "POST",9 "endpoint": "",10 "headers": { "Content-Type": "application/json" },11 "body": { "instances": "{{ instances }}" },12 "variables": [{ "name": "instances", "type": "String" }],13 "json_paths": [14 { "name": "prediction0", "path": "$.predictions[0]" },15 { "name": "deployedModelId", "path": "$.deployedModelId" }16 ]17 }18 ]19}Pro tip: If your model returns a complex nested object in predictions[0], generate JSON paths for each field you need individually — for example $.predictions[0].label and $.predictions[0].confidence — rather than trying to bind the whole object to a single widget.
Expected result: The FlutterFlow API Calls panel shows a 'VertexAI' group with a 'Predict' call. Running the Test in FlutterFlow returns real predictions from your model via the Cloud Function proxy.
Build the prediction UI and bind predictions to widgets
Now add a screen in FlutterFlow that collects the input your model needs and displays the prediction. The exact UI depends on your model type, but the wiring pattern is the same for all models. For a text or tabular model: add a TextField widget where users enter the input (e.g. a product name, a sentence, or a set of numbers). Add an App State variable named `predictionResult` of type String. Place a Button labeled 'Get Prediction'. In the button's Actions panel, click + Add Action → Backend/Database → API Request, select the VertexAI group, select Predict, and set the `instances` variable to your serialized input — for simple string inputs you can build the JSON inline using FlutterFlow's string interpolation: `["${your_text_input}"]` but for structured inputs you may need a Dart Custom Action to build the JSON string first. After the API Request action completes, add a Set App State action that stores the `prediction0` JSON path result into `predictionResult`. Add a Text widget on the screen bound to `predictionResult` to display the output. For image inputs: add a FilePicker or camera button, upload the image to Firebase Storage using the FlutterFlow Upload action, get the GCS URI (`gs://your-bucket/...`), pass that URI as the instances value to the Predict call, and display the returned label or confidence score. Test in FlutterFlow Run Mode by entering a sample input and clicking Get Prediction. Confirm the Text widget updates with a real prediction label or value from your Vertex AI model.
Pro tip: Store the last prediction result in Firestore (collection: prediction_history, fields: input, prediction, timestamp, uid) so users can review past predictions. This also helps you monitor what inputs your model is receiving in production.
Expected result: Entering an input and tapping Get Prediction calls the Cloud Function proxy, receives a Vertex AI prediction, and displays it in the Text widget on the prediction screen. The full round-trip completes within a few seconds.
Handle token expiry, quota errors, and web CORS
Vertex AI access tokens expire after approximately one hour. In the current proxy architecture, the Cloud Function mints a fresh token on every request using `client.getAccessToken()`, which is correct — the `google-auth-library` handles caching the token for its lifetime and only fetches a new one when needed. You do not need to implement token refresh logic in FlutterFlow itself. For quota errors: Vertex AI enforces per-model prediction quotas. If your app calls the endpoint too frequently or with too many instances in a single request, the API returns a 429 or a `RESOURCE_EXHAUSTED` error. Add error handling in the FlutterFlow Action Flow Editor: after the API Request action, add an If/Else condition checking whether the HTTP status code is not 200. If the condition is true, show a Snackbar widget with a user-friendly message like 'Our AI service is busy — please try again in a moment.' Do not surface the raw Google error message to users. For web builds: because your FlutterFlow web app calls your Cloud Function — not Google's API directly — CORS is already handled. The Cloud Function sets `Access-Control-Allow-Origin: *` and returns a 204 for OPTIONS preflight requests. Mobile builds (iOS and Android) are not affected by CORS at all. If you see CORS errors in web preview, verify that the function code includes the CORS headers before any other logic and that the OPTIONS method returns early with status 204. For production, consider adding FlutterFlow Firebase Authentication and requiring a valid Firebase ID token in the Cloud Function (`req.headers.authorization`) so that only authenticated users of your app can trigger Vertex AI predictions. This prevents anonymous abuse if someone discovers your Cloud Function URL.
1// Add to Cloud Function: optional auth check2const admin = require('firebase-admin');3if (!admin.apps.length) admin.initializeApp();45// Near the top of the handler, after CORS:6const authHeader = req.headers.authorization || '';7if (!authHeader.startsWith('Bearer ')) {8 res.status(401).json({ error: 'Unauthorized' });9 return;10}11const idToken = authHeader.split('Bearer ')[1];12try {13 await admin.auth().verifyIdToken(idToken);14} catch (e) {15 res.status(401).json({ error: 'Invalid token' });16 return;17}Pro tip: If you add Firebase ID token verification to the Cloud Function, pass the token from FlutterFlow by adding an Authorization header variable to the API Group: in FlutterFlow, set the header value to `Bearer {{ authToken }}` and pass `currentUserJwtToken` as the variable value in the Action.
Expected result: Error states are handled gracefully — users see friendly messages for quota errors and slow responses. Web builds work without CORS errors. In production, the Cloud Function rejects unauthenticated requests.
Test end to end and verify the region configuration
The most common failure with Vertex AI integrations is a region mismatch — if your endpoint was deployed in `us-central1` but the Cloud Function's VERTEX_REGION environment variable is set to `us-east1`, every prediction call returns a 404 with a generic 'not found' message. Before declaring the integration complete, verify the region by opening the Vertex AI → Online Prediction → Endpoints page in the Cloud Console, clicking your endpoint, and confirming the region shown in the URL and details panel matches your Cloud Function environment variable exactly. Run a full end-to-end test from FlutterFlow's Run Mode: enter a real input, submit it, watch the network requests in your browser's developer tools (for web preview) to confirm the call goes to your Cloud Function URL and the Cloud Function URL returns a 200 with predictions in the response body. For mobile testing, use FlutterFlow's Test Mode on a device or use the Run button with a connected Android/iOS device. Also verify that the `deployedModelId` field in the predictions response matches the model version you expected. This confirms that the correct model version is serving predictions. If you have multiple model versions deployed to the same endpoint, you can specify a traffic split in the Cloud Console to control which version handles each prediction request. If you would like help setting up the Cloud Function proxy, configuring the service account permissions, or troubleshooting the Vertex AI response format, the RapidDev team builds FlutterFlow AI integrations like this regularly — reach out for a free scoping call at rapidevelopers.com/contact.
Pro tip: Add a loading spinner (CircularProgressIndicator widget in a conditional Visibility group) that appears while the API call is in flight. Set an App State boolean `isLoading` to true before the API Request action and false after it completes.
Expected result: End-to-end predictions work from FlutterFlow Run Mode. The region matches, the Cloud Function returns 200 with valid predictions, and the UI displays the result. Error states show friendly messages instead of raw API errors.
Common use cases
Image classification app that runs a custom Vertex AI vision model
A FlutterFlow mobile app where users photograph products, plants, or medical images and receive a classification label and confidence score from a custom TensorFlow model deployed on Vertex AI. The app uploads the image to Cloud Storage, sends the GCS URI to the Cloud Function proxy, which calls the Vertex AI :predict endpoint and returns the top prediction labels. Results are displayed in a Card widget bound to the predictions array.
Build a FlutterFlow screen with a camera button. When the user takes a photo, upload it to Firebase Storage and then call the Vertex AI Cloud Function proxy with the storage URL. Display the top 3 prediction labels and confidence scores in a Column of Card widgets.
Copy this prompt to try it in FlutterFlow
Demand forecasting dashboard that queries a tabular prediction model
A FlutterFlow business app that sends product ID and historical sales figures as a JSON instance to a tabular regression model on Vertex AI, receiving a demand forecast for the next 30 days. The predicted value is displayed in a FlutterFlow Line Chart widget alongside historical actuals stored in Firestore, giving inventory managers a visual forecast tool built entirely in FlutterFlow without any custom ML code on the client.
Build a FlutterFlow page with dropdowns for product category and date range. On selection, call the Vertex AI proxy with the input instances and plot the returned predictions as a line chart next to the historical Firestore data.
Copy this prompt to try it in FlutterFlow
Natural language intent classifier powering in-app chat routing
A FlutterFlow customer support app where incoming user messages are sent to a fine-tuned text classification model on Vertex AI, which returns an intent label like 'billing', 'technical', or 'general'. The intent label determines which support queue the conversation is routed to, managed via Firestore. FlutterFlow reads the route from Firestore and displays the correct support screen without any client-side ML.
Build a FlutterFlow chat entry screen. When the user submits a message, send it to the Vertex AI proxy, read the returned intent label from predictions[0], and navigate to the corresponding support screen based on that label.
Copy this prompt to try it in FlutterFlow
Troubleshooting
Cloud Function returns 404 when calling Vertex AI :predict endpoint
Cause: The region in the Vertex AI endpoint URL does not match the region where the endpoint was actually deployed. The URL format `https://REGION-aiplatform.googleapis.com/v1/projects/...` is region-sensitive, and an incorrect region returns a generic 404 rather than a helpful auth error.
Solution: Open the Vertex AI console (console.cloud.google.com/vertex-ai), click Online Prediction → Endpoints, and click your endpoint. The region is shown in the endpoint details and in the page URL. Update the VERTEX_REGION environment variable in your Cloud Function to exactly match that region (e.g. 'us-central1', 'europe-west4') and re-deploy the function.
Cloud Function returns 403 Forbidden when calling Vertex AI
Cause: The service account used by the Cloud Function does not have the Vertex AI User IAM role on the project, or the Vertex AI API is not enabled in the Google Cloud project. The service-account JSON key may also be for a different Google Cloud project than the one where the endpoint is deployed.
Solution: In the Cloud Console, go to IAM & Admin → IAM. Find the service account email and confirm it has the 'Vertex AI User' role. If not, click the pencil edit icon and add the role. Also navigate to APIs & Services → Enabled APIs and confirm 'Vertex AI API' is enabled. Verify the PROJECT_ID environment variable in your Cloud Function matches the project where the endpoint is deployed.
Prediction returns 400 Bad Request with 'Invalid input instances' or shape mismatch error
Cause: The instances array sent to Vertex AI does not match the format the model was trained on. Models expect a specific tensor shape and data type — sending a string where a number is expected, or an array of wrong length, causes input validation to fail at the model level.
Solution: Open the Vertex AI endpoint details in Cloud Console and check the 'Sample request' tab, which shows the exact expected instances format for your model. Ensure your FlutterFlow action constructs the instances JSON string to match that format exactly. If the model expects numeric arrays (for tabular data), ensure values are numbers not strings in the serialized JSON.
XMLHttpRequest error or No Access-Control-Allow-Origin header in FlutterFlow web preview
Cause: The Cloud Function is not setting CORS headers before processing the request, or the OPTIONS preflight request is not being handled and returning 204 before the main logic runs. This only appears in web builds — mobile builds do not enforce CORS.
Solution: Add CORS headers at the very start of the Cloud Function handler, before any other logic. Return a 204 response immediately when req.method === 'OPTIONS'. The headers needed are Access-Control-Allow-Origin: * and Access-Control-Allow-Headers: Content-Type. Re-deploy the function after adding these headers.
1res.set('Access-Control-Allow-Origin', '*');2res.set('Access-Control-Allow-Headers', 'Content-Type');3if (req.method === 'OPTIONS') { res.status(204).send(''); return; }Best practices
- Store the service-account JSON as a base64-encoded environment variable or in Google Secret Manager — never hardcode it in Cloud Function source code or commit it to a repository
- Use the google-auth-library npm package to handle OAuth token minting and caching automatically, rather than building the JWT signing logic manually
- Add Firebase ID token verification to the Cloud Function so only authenticated users of your app can trigger Vertex AI predictions and drain your quota
- Include the region name explicitly in VERTEX_REGION and double-check it matches the deployed endpoint region — a region mismatch causes a silent 404 that is hard to diagnose
- Add user-friendly error handling in FlutterFlow's Action Flow Editor for 429 quota errors and 503 service-unavailable responses — never show raw Google API error messages to end users
- Cache prediction results in Firestore for identical inputs to reduce Vertex AI calls and stay within free quota tiers during development
- Test the Cloud Function directly with curl or Postman before building the FlutterFlow UI — confirm the response format and JSON paths before attempting to parse them in FlutterFlow
- Monitor Vertex AI prediction latency in the Cloud Console — add a loading indicator in FlutterFlow so users know the prediction is in progress, especially for large models with cold-start latency
Alternatives
If you want to run ML models offline without any Google Cloud account or per-prediction costs, TensorFlow Lite via the tflite_flutter Custom Action runs the model directly on the user's device — no service account or Cloud Function needed.
For text generation, summarization, and chat tasks, OpenAI's Chat Completions API is simpler to set up than Vertex AI — no service account JWT flow, just a Bearer sk-... key routed through a Cloud Function proxy.
Azure ML offers a similar managed model serving REST API for teams already in the Microsoft ecosystem, with a managed endpoint pattern that mirrors Vertex AI's :predict structure.
Frequently asked questions
Can I call the Vertex AI endpoint directly from FlutterFlow without a Cloud Function?
Technically you could construct the Bearer token and call the Vertex AI URL directly in an API Call, but you cannot safely do so because the service-account private key required to mint that token must never be stored in FlutterFlow. If you placed the key in an App Constant or API Call header, it would ship in the compiled APK where anyone could extract it and use it to access your entire Google Cloud project. The Cloud Function proxy is the only safe approach.
Does Google Cloud AI Platform cost money?
Vertex AI charges per prediction request at rates that vary by model type — there is no free inference tier for custom deployed models. Online prediction costs are based on the number of prediction requests and the machine type of the endpoint. Check the current Vertex AI pricing page at cloud.google.com/vertex-ai/pricing because rates change over time. Enable billing alerts in the Google Cloud Console to avoid unexpected charges during development.
How do I handle Vertex AI access token expiry in my FlutterFlow app?
You do not need to handle token expiry in FlutterFlow at all. The Cloud Function proxy mints a fresh token for each prediction request using the google-auth-library, which caches the token and only fetches a new one when the current one is close to expiring. From FlutterFlow's perspective, every call to the proxy just gets a fresh valid prediction — the token lifecycle is invisible to the client app.
Does this work for Gemini models on Vertex AI as well?
Yes, but Gemini uses a different endpoint URL structure (`https://REGION-aiplatform.googleapis.com/v1/projects/{id}/locations/{region}/publishers/google/models/{model}:generateContent`) and a different request body format. The auth pattern — service account JWT via google-auth-library in a Cloud Function — is identical. You would create a separate API Call in your FlutterFlow API Group for the generateContent endpoint, or build a separate proxy function for Gemini calls.
Can I use App Engine or Cloud Run instead of Cloud Functions as the proxy?
Yes. The proxy pattern works with any server-side compute platform — Cloud Functions, Cloud Run, App Engine, or even a self-hosted Express server. The key requirement is that the service-account JSON lives on the server, not in the Flutter client. Cloud Functions is the simplest option for FlutterFlow projects that already use Firebase because it integrates directly with the same Google Cloud project and Firebase console.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation