# UptimeRobot

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

## TL;DR

Connect FlutterFlow to UptimeRobot using the API Calls panel to POST to https://api.uptimerobot.com/v2/getMonitors with your api_key in the form body—not a Bearer header. UptimeRobot's v2 API is POST-only with application/x-www-form-urlencoded content, which trips up founders who copy a GET/Bearer pattern. Use a read-only API key and refresh on demand to stay within the free plan's rate limits.

## Build a Free Uptime Monitoring Dashboard in FlutterFlow with UptimeRobot

UptimeRobot is one of the most popular uptime monitors in the world specifically because it has a genuinely useful free tier: 50 monitors, 5-minute check intervals, email and push alerts, and API access—all at no cost. For a founder who wants to see their sites' status in a custom mobile app without paying for Pingdom or Datadog, UptimeRobot is the natural starting point.

The FlutterFlow integration is straightforward in concept but has one important technical quirk that trips up almost everyone who attempts it: the UptimeRobot v2 API is entirely POST-based, and all parameters—including your API key—travel in the request body as URL-encoded form fields, not as query parameters on the URL and not as a Bearer token in a header. If you set up your API Group as a GET request with an Authorization header (the pattern used by Pingdom or most other APIs), every call will return a 400 or 401 error. Getting this single detail right makes the integration work immediately.

UptimeRobot's free plan includes around 10 requests per minute on the API (verify current limits at uptimerobot.com/api)—enough for an on-demand refresh pattern but not for rapid timer-based polling. Paid tiers (Team and Pro, starting around $7/month—verify current pricing) offer more monitors, shorter check intervals, and higher API limits. For most founders reading this, the free tier with 50 monitors is more than sufficient for an internal ops dashboard.

## Before you start

- A UptimeRobot account (free at uptimerobot.com—no credit card required)
- At least one monitor configured in your UptimeRobot account to test the API response
- A read-only API key generated from My Settings → API Settings in the UptimeRobot dashboard
- A FlutterFlow project (any plan) with at least one screen to place the status dashboard
- Basic familiarity with FlutterFlow's API Calls panel and widget binding

## Step-by-step guide

### 1. Generate a read-only API key in UptimeRobot

Log in to your UptimeRobot account at app.uptimerobot.com. Click your account avatar in the top right corner and choose My Settings. Scroll down to the API Settings section.

You will see two types of API keys listed here. The Main API Key gives full read and write access to your entire account—it can create, modify, and delete monitors. Below that, you can generate per-monitor or read-only keys. For this FlutterFlow integration, create or copy a read-only API key rather than the Main API Key. The reason is that your API key will be configured inside FlutterFlow's API Group at build time, and while this is safer than hardcoding it in Dart, it is still a client-side configuration that a sufficiently motivated attacker could extract from device traffic. A read-only key means the worst an attacker could do is read your monitor list—they cannot delete or modify your monitors.

If you only see the Main API Key and no read-only option, check whether your UptimeRobot plan includes per-monitor key generation. On the free plan, the Main API Key is typically the only option—in which case use it for a private internal app and understand its scope.

Copy the API key and store it securely. Do not place it in any code file or version control system.

**Expected result:** You have a UptimeRobot API key (preferably read-only) copied to a secure location, ready to paste into FlutterFlow.

### 2. Create the UptimeRobot API Group with POST and form-urlencoded

In FlutterFlow, click API Calls in the left navigation panel. Click + Add and choose Create API Group. Name the group UptimeRobot and set the Base URL to https://api.uptimerobot.com/v2.

This is where the most important configuration difference lives compared to other APIs. On the Headers tab, add a Content-Type header with the value application/x-www-form-urlencoded. This tells UptimeRobot's server how to parse the request body you will send. Do NOT add an Authorization header here—UptimeRobot does not use Bearer tokens. The api_key travels in the request body, not a header.

Leave the HTTP method at the group level blank for now (you will set it per API Call). Click Save.

Why does this matter so much? Most REST APIs that developers know—Stripe, Twilio, GitHub—accept a Bearer token in an Authorization header and return data in response to GET requests. UptimeRobot's v2 API was designed differently: it only accepts POST requests, and all parameters including authentication are sent as form fields in the body. If you copy the pattern from a typical API integration and set up a GET request with a Bearer header, UptimeRobot will return an error on every single call. Recognizing this upfront saves an hour of debugging.

```
{
  "group_name": "UptimeRobot",
  "base_url": "https://api.uptimerobot.com/v2",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  "note": "No Authorization header — api_key goes in the form body"
}
```

**Expected result:** A 'UptimeRobot' API Group appears in the API Calls panel with the Base URL set to https://api.uptimerobot.com/v2 and a Content-Type header of application/x-www-form-urlencoded. No Authorization header is present.

### 3. Add the POST /getMonitors API Call with form body fields

Inside the UptimeRobot API Group, click + Add API Call. Name it Get Monitors, set the HTTP method to POST, and set the endpoint path to /getMonitors.

Now go to the Body tab—not the Headers tab, and not a query parameter field. Set the body type to Form URL Encoded (also shown as x-www-form-urlencoded in the dropdown). Add the following form fields:

- api_key: Enter your UptimeRobot API key directly as a value. This is a static string entered at build time.
- format: Set to json. This tells UptimeRobot to return JSON rather than XML.
- logs: Optionally set to 1 to include recent alert log data in the response.

Do NOT add api_key as a URL query parameter or in the path. It must be a form field in the encoded body. This is the #1 setup mistake—developers add it as a query param (?api_key=...) and then wonder why they get 400 responses.

Once you have configured the body fields, click Save and go to the Response & Test tab. Click Send. You should receive a JSON response with a stat field equal to 'ok' and a monitors array. If you see stat: 'fail' with an error key, the api_key is wrong or in the wrong location. A successful response will look like the example below.

Click Generate JSON Paths to let FlutterFlow parse the response structure. Key paths to use: $.monitors[:].friendly_name, $.monitors[:].url, $.monitors[:].status (integer: 2=up, 8=seems down, 9=down, 0=paused), $.monitors[:].average_response_time.

```
// POST /getMonitors — form body (NOT query params)
// Content-Type: application/x-www-form-urlencoded
// Body fields:
//   api_key=YOUR_KEY&format=json&logs=1

// Example successful response (partial)
{
  "stat": "ok",
  "pagination": { "offset": 0, "limit": 50, "total": 3 },
  "monitors": [
    {
      "id": 7654321,
      "friendly_name": "My Production Site",
      "url": "https://mysite.com",
      "type": 1,
      "status": 2,
      "average_response_time": "143",
      "all_time_uptime_ratio": "99.97"
    }
  ]
}

// Status codes:
// 0  = paused
// 2  = up (green)
// 8  = seems down (yellow — check in progress)
// 9  = down (red)
```

**Expected result:** The Test tab for your Get Monitors call returns a JSON object with stat='ok' and a monitors array containing your configured monitors. FlutterFlow has generated JSON Paths you can use for widget binding.

### 4. Create a Data Type and bind to a status ListView

To make the response easy to work with, create a custom Data Type. In FlutterFlow, go to Data Types in the left navigation and click + Add Data Type. Name it UptimeMonitor and add these fields: id (Integer), friendlyName (String), url (String), status (Integer), averageResponseTime (String), uptimeRatio (String).

Now open your status screen and add a ListView widget. In the Actions panel, add a Backend/API Call action that fires on page load, targeting Get Monitors in your UptimeRobot API Group. Set up widget binding on the ListView to use the API response, mapping each monitor in the $.monitors array to a list item.

Inside the ListView, design a card for each monitor row. Add a Text widget bound to item.friendlyName for the monitor name. Add a smaller Text widget bound to item.url for the URL being checked.

For the status indicator, add a Container widget and set its background color using a Conditional Expression:
- If item.status == 2 → Color #4CAF50 (green, up)
- If item.status == 9 → Color #F44336 (red, down)
- If item.status == 8 → Color #FF9800 (orange, seems down)
- Otherwise (0, paused) → Color #9E9E9E (grey)

Add a Text widget inside this container showing a human-readable label: 'UP', 'DOWN', 'CHECKING', or 'PAUSED'.

For pull-to-refresh, wrap the ListView in a RefreshIndicator widget and wire its onRefresh callback to trigger the Get Monitors API Call again. This keeps data fresh without hammering the API on an automatic timer. UptimeRobot's free plan rate limit is approximately 10 requests per minute—verify the current limit in UptimeRobot's API documentation before setting up any automatic refresh logic.

**Expected result:** Your status screen displays a list of all UptimeRobot monitors with color-coded status badges, monitor names, URLs, and uptime ratios. Green/red/orange/grey indicators communicate health at a glance.

### 5. Handle rate limits and add a web-build CORS note

UptimeRobot's free plan applies a rate limit to API calls (approximately 10 requests per minute—verify at uptimerobot.com/api). For a human-driven pull-to-refresh pattern, this is more than enough: a user is unlikely to refresh faster than once every few seconds manually. Where you need to be careful is any automatic background refresh.

If you are considering adding a periodic timer to auto-refresh the monitor list (for example, refreshing every 30 seconds), calculate how many API calls per minute that represents across all users of your app. If this is a personal dashboard used by only you, a 60-second timer would use 1 call/minute—well within limits. If you distribute this app to 50+ users, multiply accordingly. For high-user-count scenarios, route the UptimeRobot API call through a Firebase Cloud Function that caches the response for 60 seconds and serves all app users from a single API call.

For web builds specifically: FlutterFlow's web preview runs in a browser, and browsers enforce CORS (Cross-Origin Resource Sharing). If you attempt to call the UptimeRobot API directly from a browser-rendered web build of your FlutterFlow app, you may encounter an 'XMLHttpRequest error' because UptimeRobot may not include the browser-required CORS headers in its responses. This does not affect iOS or Android native builds—only the browser-rendered web version. If your app needs to run as a web app, route the UptimeRobot call through a Firebase Cloud Function or Supabase Edge Function that adds proper CORS headers and acts as a proxy.

Test your app on a real iOS or Android device or emulator for the most reliable results. The FlutterFlow browser-based Run mode may exhibit different behavior from a deployed app, particularly for API calls.

```
// Firebase Cloud Function proxy example (Node.js)
// Deploy to Firebase to avoid CORS issues in web builds
// and to add server-side caching

const functions = require('firebase-functions');
const axios = require('axios');

exports.getUptimeRobotMonitors = functions.https.onRequest(async (req, res) => {
  // Add CORS headers
  res.set('Access-Control-Allow-Origin', '*');
  res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
  if (req.method === 'OPTIONS') {
    res.status(204).send('');
    return;
  }

  try {
    const response = await axios.post(
      'https://api.uptimerobot.com/v2/getMonitors',
      new URLSearchParams({
        api_key: process.env.UPTIMEROBOT_API_KEY, // Secret in Firebase env
        format: 'json',
        logs: '0',
      }),
      { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
    );
    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: 'Failed to fetch monitors' });
  }
});
```

**Expected result:** Your app respects UptimeRobot's rate limits by only refreshing on user action. If you need web support, you have a Firebase Cloud Function proxy ready to route calls and handle CORS correctly.

## Best practices

- Always use a read-only UptimeRobot API key—if the key is ever extracted from device traffic, the attacker can only read monitor status, not create, modify, or delete monitors.
- Keep the api_key in the API Call's form body as a static value entered at build time—never write it into a Custom Action Dart string that compiles into the client app binary.
- Refresh monitor data only on page load and explicit user pull-to-refresh; avoid timer-based automatic polling to stay within the free plan's API rate limit.
- Map UptimeRobot's integer status codes (0, 2, 8, 9) to display strings and colors in a single Custom Function so you update the mapping in one place if UptimeRobot ever adds new codes.
- Handle the stat='fail' API response explicitly in your app—show an error state widget with a retry button rather than leaving users staring at an empty list.
- For web builds or high-traffic deployments, route the UptimeRobot call through a Firebase Cloud Function proxy that adds CORS headers and caches responses to stay within rate limits.
- Test the integration on a real iOS or Android device rather than only in FlutterFlow's browser-based Run mode, since CORS behavior differs between native and web builds.
- Verify current UptimeRobot pricing and API rate limits at uptimerobot.com before launch—the free tier limits and paid plan pricing have changed over time.

## Use cases

### Personal site-status mobile app on the free tier

A bootstrapped founder running multiple small websites and APIs builds a FlutterFlow app to replace opening the UptimeRobot web console every morning. The app shows all 50 free monitors in a list, color-codes each by status, and lets the founder refresh with a pull gesture. Total cost: $0—both UptimeRobot and this basic FlutterFlow use fall within free tiers.

Prompt example:

```
Build a screen showing all UptimeRobot monitors in a list. Each row should show the monitor name, URL being monitored, and a colored status badge: green for up, red for down, grey for paused. Add pull-to-refresh at the top.
```

### Internal ops dashboard for a small dev team

A small development agency shares a FlutterFlow app with their team so every engineer can instantly check whether any client sites are down during business hours, without needing a UptimeRobot account login. The app shows monitor name, last check time, and response time alongside the status, making it a quick sanity check before starting client calls.

Prompt example:

```
Create a monitor list screen that shows each monitor's friendly name, status, response time in milliseconds, and the time of the last check. Sort monitors so 'down' ones appear at the top. Add a refresh button in the app bar.
```

### Client status screen embedded in a service app

A developer selling a hosted SaaS tool builds a FlutterFlow mobile app for their customers and embeds a simple status panel that shows whether their specific service endpoints are up. Using a read-only per-monitor API key, the app pulls status for only the relevant monitors without exposing the full account.

Prompt example:

```
Show a filtered list of monitors using a monitor-specific read-only API key. Display each monitor's current status and uptime ratio over the last 30 days. Use a clean card layout with the service name prominently displayed.
```

## Troubleshooting

### API returns {"stat":"fail","error":{"type":"wrong_api_key"}} or similar

Cause: The api_key value is incorrect, the key has been regenerated in UptimeRobot since you pasted it into FlutterFlow, or the key was accidentally added as a URL query parameter instead of a form body field.

Solution: Open API Calls → UptimeRobot → Get Monitors → Body tab. Confirm api_key is listed as a form field (not a URL parameter) and that its value matches the key currently shown in UptimeRobot's My Settings → API Settings. If you regenerated the key recently, update the value in FlutterFlow's body field and re-test.

### 400 Bad Request on every call even though the key looks correct

Cause: The HTTP method is set to GET instead of POST, or the Content-Type header is missing or set to application/json instead of application/x-www-form-urlencoded. UptimeRobot v2 requires POST with form encoding—it does not accept GET requests.

Solution: Select the Get Monitors API Call and confirm the Method dropdown shows POST. Then check the API Group headers and ensure Content-Type is set to application/x-www-form-urlencoded. Check the Body tab—if it shows a JSON body editor instead of form fields, delete the current body config and re-add it as Form URL Encoded. Re-test.

### XMLHttpRequest error — monitors load on device but fail in the browser/web preview

Cause: UptimeRobot's API does not include CORS headers in its responses. Browser-rendered web builds of FlutterFlow enforce CORS and block the request, while native iOS/Android builds do not enforce CORS and work fine.

Solution: For web builds, deploy a Firebase Cloud Function or Supabase Edge Function that proxies the UptimeRobot call server-side and adds 'Access-Control-Allow-Origin: *' headers. Update your FlutterFlow API Group's base URL to point at the proxy Cloud Function instead of api.uptimerobot.com directly. See Step 5 for a sample Cloud Function.

### All monitors show status 0 (paused) even though UptimeRobot shows them as active

Cause: The JSON Path mapping is targeting the wrong field, or the status field is being cast to a String in FlutterFlow when it should remain an Integer. String comparison against the integer value 2 will always fail.

Solution: In your UptimeMonitor Data Type, ensure the status field is mapped as an Integer type. In the JSON Path binding, confirm you are using $.monitors[:].status with no additional string transformation. In your conditional color expression, compare item.status == 2 (integer equality) rather than item.status == '2' (string comparison).

## Frequently asked questions

### Why does the UptimeRobot API use POST instead of GET like most REST APIs?

UptimeRobot's v2 API was designed with a form-POST style common in older web APIs, where a single endpoint (/getMonitors) accepts different query behaviors through body parameters rather than through different HTTP methods and URLs. This is different from modern RESTful APIs, but it's a valid design. The key consequence for FlutterFlow is that you must configure the API Call as POST and use the Form URL Encoded body type—not GET with query parameters.

### Can I show monitors for just one specific website, not my entire account?

Yes. The POST /getMonitors endpoint accepts a monitors parameter in the form body, which accepts a comma-separated list of monitor IDs to filter the response. Find your monitor IDs by first calling getMonitors without filters to see all monitors, then note the id value for the ones you want. On subsequent calls, add a monitors form field with the value set to those specific IDs.

### Is the free UptimeRobot plan sufficient for this FlutterFlow integration?

For a personal or small-team internal dashboard, yes. The free plan includes 50 monitors, 5-minute check intervals, full API access, and approximately 10 API requests per minute. An on-demand pull-to-refresh pattern used by a handful of people will comfortably stay within these limits. If you're distributing the app to many external users who all might refresh simultaneously, consider a paid tier or a caching proxy.

### Can I use this integration to create or pause monitors from my FlutterFlow app?

Technically yes—UptimeRobot's API supports creating (newMonitor) and editing (editMonitor) monitors via POST. However, for a client-side FlutterFlow app, using write-capable endpoints is risky because your API key could be extracted from device network traffic. Stick to read-only calls for a monitoring dashboard. If you need to manage monitors from an app, route the write calls through a Firebase Cloud Function that authenticates the user before performing any write operations.

### My integration works on Android but fails in FlutterFlow's web preview. What's wrong?

This is a CORS issue. Browser-rendered web apps enforce Cross-Origin Resource Sharing policies, and UptimeRobot's API may not return the CORS headers browsers require. Native Android and iOS builds bypass CORS enforcement because they're not running in a browser context. See Step 5 for a Firebase Cloud Function proxy pattern that resolves CORS for web builds. If you only need this app on mobile (iOS/Android), you can ignore the web preview behavior.

### What do I do if I need real-time push alerts when a monitor goes down?

UptimeRobot supports webhook alert notifications—configure these in UptimeRobot's Alert Contacts settings. Point the webhook at a Firebase Cloud Function that receives the alert payload and sends an FCM push notification to your FlutterFlow app via Firebase Cloud Messaging. This gives you near-instant down alerts without polling the API at all. RapidDev's team builds these webhook-to-FCM integrations regularly—free scoping call at rapidevelopers.com/contact.

---

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