# Edmodo

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 30 minutes to choose a platform + 45-90 minutes to build the FlutterFlow integration
- Last updated: July 2026

## TL;DR

Edmodo shut down permanently in September 2022 — its API and all services no longer exist. This guide helps you migrate to an active platform: Google Classroom (OAuth 2.0), Canvas LMS (API token), or Moodle (Web Services token). Once you choose a replacement, connect it to FlutterFlow using the appropriate API Group or custom action, and rebuild the social-feed features in Firebase or Supabase.

## Edmodo Shut Down in 2022 — Here Is What to Build Instead

If you landed here looking for an Edmodo API integration, you need to know this first: Edmodo permanently shut down all services in September 2022. The platform, the API, and all user data are gone. Any older tutorial or documentation describing an 'active Edmodo API' is describing something that no longer exists. Building a FlutterFlow integration against Edmodo is not possible — and has not been possible since 2022.

The good news is that the social-classroom features Edmodo was known for (class feeds, assignment posting, parent-teacher communication, roster management) are all available through active, well-maintained platforms that have real APIs. Depending on what you need, one of three replacements will fit: Google Classroom for schools already using Google Workspace for Education, Canvas LMS for institutions that want a full-featured LMS with a conventional REST API, or Moodle for open-source self-hosted setups with complete control. All three have documented APIs you can connect to FlutterFlow today.

This guide helps you pick the right replacement, explains how each one connects to FlutterFlow, and shows you how to rebuild the social-feed component that was Edmodo's signature feature — using Firebase or Supabase as your app's native backend for the feed data. If you had an existing Edmodo-based workflow, the migration means starting fresh (Edmodo's data export service ended with the platform), but the end result will be a more robust integration with a platform that is actively maintained and has a real developer ecosystem.

## Before you start

- An active account on your chosen replacement platform: Google Classroom (Google Workspace for Education account), Canvas LMS (institution account or free-for-teacher tier), or Moodle (self-hosted or Moodle Cloud instance)
- A FlutterFlow project with Firebase or Supabase enabled for the social-feed component and Cloud Function proxy
- Understanding that no Edmodo data can be migrated — the platform shut down completely in September 2022
- For Google Classroom: a Google Cloud project with the Classroom API enabled and an OAuth consent screen configured
- For Canvas or Moodle: an API access token from your institution's admin or a self-generated token from your account settings

## Step-by-step guide

### 1. Acknowledge the Edmodo shutdown and choose your replacement platform

Before writing a single line of configuration, confirm that you are not trying to build against Edmodo. Edmodo shut down permanently in September 2022. There are no API endpoints, no authentication tokens, no account login, and no data exports available. The domain may still exist but the platform and all associated developer services are gone. Any code or configuration targeting Edmodo will not work.

Now choose your replacement based on your context:

**Google Classroom** is the right choice if your school or organization already uses Google Workspace for Education. It has a free API, strong institutional adoption, and covers the core Edmodo use cases: class announcements, assignments, rosters, and coursework. The integration in FlutterFlow uses a `custom_action` with the `google_sign_in` package and OAuth 2.0 with education scopes. The main complexity is the OAuth consent screen setup in Google Cloud Console.

**Canvas LMS** is the right choice if your institution has a Canvas deployment. Canvas has one of the most comprehensive LMS REST APIs available — it covers courses, enrollments, grades, assignments, announcements, and messaging. The FlutterFlow integration uses a conventional API Group with a bearer token, routed through a Cloud Function proxy. Canvas offers a free-for-teacher tier at canvas.instructure.com.

**Moodle** is the right choice for self-hosted environments or institutions already on Moodle. Its Web Services API uses a unique function-based pattern where every call hits the same endpoint with a `wsfunction` query parameter. The FlutterFlow integration uses an API Group with this pattern. Moodle is open-source and free — the institution pays only for hosting.

Pick one platform and proceed to the relevant configuration steps. Each platform has its own dedicated guide in the FlutterFlow integrations library (see related integrations below) with full step-by-step detail.

**Expected result:** You have confirmed you are not building against Edmodo, and you have chosen Google Classroom, Canvas LMS, or Moodle as your replacement platform.

### 2. Set up the Cloud Function credential proxy for your chosen platform

Regardless of which platform you choose, credentials must never live in your FlutterFlow Dart code. A Firebase Cloud Function (or Supabase Edge Function) handles all credential management. The implementation differs slightly per platform:

**For Google Classroom:** The OAuth 2.0 client secret must not be in Dart. Set up a Cloud Function that accepts a refresh token (obtained on-device by the `google_sign_in` custom action) and exchanges it for a new access token via Google's token endpoint. The function stores the client secret in environment variables and returns only the short-lived access token to FlutterFlow.

**For Canvas LMS:** Your Canvas API token (generated in Canvas Account → Settings → New Access Token) is sensitive — it gives full account access. Store it in a Cloud Function environment variable. The function acts as a proxy: FlutterFlow calls the Cloud Function with the Canvas endpoint path and parameters, and the function forwards the request to your Canvas instance with the token in the Authorization header.

**For Moodle:** The Moodle Web Services token (generated in Site administration → Server → Web services → Manage tokens) must also be proxied. The Cloud Function accepts the `wsfunction` name and parameters, then calls `https://your-moodle.edu/webservice/rest/server.php` with the token and `moodlewsrestformat=json`.

Deploy your chosen proxy function to Firebase and note the HTTPS trigger URL — you will configure this as a separate API Group in FlutterFlow named after your chosen platform ('Classroom Proxy', 'Canvas Proxy', or 'Moodle Proxy').

```
// Cloud Function proxy example for Canvas LMS
// index.js (Node.js 18+)
const functions = require('firebase-functions');
const axios = require('axios');

const CANVAS_TOKEN = process.env.CANVAS_API_TOKEN;
const CANVAS_BASE = process.env.CANVAS_BASE_URL; // e.g. https://yourschool.instructure.com

exports.canvasProxy = functions.https.onRequest(async (req, res) => {
  if (req.method !== 'POST') return res.status(405).send('Method Not Allowed');

  const { endpoint, method = 'GET', params = {} } = req.body;
  try {
    const response = await axios({
      method,
      url: `${CANVAS_BASE}/api/v1${endpoint}`,
      headers: { Authorization: `Bearer ${CANVAS_TOKEN}` },
      params: method === 'GET' ? params : undefined,
      data: method !== 'GET' ? params : undefined,
    });
    res.json(response.data);
  } catch (err) {
    const status = err.response?.status || 500;
    res.status(status).json({ error: err.message });
  }
});
```

**Expected result:** A Firebase Cloud Function is deployed and accessible via its HTTPS URL, acting as a secure proxy between FlutterFlow and your chosen LMS platform.

### 3. Configure the FlutterFlow API Group for your replacement platform

With the Cloud Function proxy deployed, set up the FlutterFlow API Group that your app will use to fetch LMS data.

In FlutterFlow, click API Calls in the left nav → + Add → Create API Group. Name it after your chosen platform ('Google Classroom', 'Canvas LMS', or 'Moodle'). Set the Base URL to your Cloud Function's HTTPS trigger URL.

**Canvas path:** Add API Calls with the `endpoint` body parameter set to the Canvas API path you need: `/courses` for course list, `/courses/{courseId}/assignments` for assignments, `/courses/{courseId}/students` for roster, `/courses/{courseId}/discussion_topics` for announcements. Each call POSTs to your Cloud Function proxy with `{ endpoint: '/courses', method: 'GET' }`. Parse the response using JSON Paths — Canvas returns arrays of objects with fields like `$.[:].id`, `$.[:].name`, `$.[:].enrollment_term_id`.

**Moodle path:** Add API Calls where each call sends `{ wsfunction: 'core_course_get_courses', params: {} }` to your Moodle proxy function. Common wsfunction values: `core_course_get_courses` (list courses), `core_user_get_users` (user lookup), `gradereport_user_get_grade_items` (grades). Parse responses with JSON Paths for the function's specific return format.

**Google Classroom path:** After the `google_sign_in` custom action runs and stores the access token in App State, configure a direct API Group (without the proxy) pointing to `https://classroom.googleapis.com/v1` with `Authorization: Bearer {{accessToken}}` as a shared header. Add calls for `/courses`, `/courses/{courseId}/students`, and `/courses/{courseId}/courseWork`.

Test each API Call in the Response & Test tab to confirm you receive real data before proceeding to widget binding.

```
// Sample JSON Paths for Canvas LMS /api/v1/courses response
// $.[:].id            → course ID
// $.[:].name          → course name
// $.[:].course_code   → short course code
// $.[:].enrollment_type → student or teacher
// $.[:].start_at      → course start date

// Sample JSON Paths for Moodle core_course_get_courses
// $[:].id             → course ID
// $[:].fullname       → full course name
// $[:].shortname      → abbreviated name
// $[:].summary        → course description
// $[:].startdate      → Unix timestamp of start date
```

**Expected result:** Your FlutterFlow project has an API Group configured for your chosen replacement platform, with at least two working API Calls that return real course and roster data.

### 4. Rebuild the Edmodo-style social feed in Firebase or Supabase

Edmodo's signature feature was the class feed — teachers and students could post updates, questions, and files in a shared stream, and parents could follow along. None of the three replacement platforms fully replicate this as a native mobile-first feed, but you can build it in Firebase or Supabase as your app's own data layer.

For **Firebase:** Create a `feeds` Firestore collection with documents for each class feed. Each document has fields: `class_id` (linked to your LMS course ID), `author_id`, `author_name`, `content` (String), `created_at` (Timestamp), `type` (String: 'announcement' | 'question' | 'assignment'), and an `attachments` array. Enable real-time listeners in FlutterFlow by using a Firestore stream query on this collection filtered by `class_id`. New posts appear instantly without refreshing.

For **Supabase:** Create a `feed_posts` table with equivalent columns. Enable the Supabase Realtime feature for this table. In FlutterFlow, use the Supabase Realtime integration (Settings & Integrations → Supabase → enable Realtime) so the feed ListView updates in real time when teachers or parents post.

Add a 'New Post' floating action button that opens a bottom sheet with a text field and an optional image upload. The post action writes to Firestore/Supabase and optionally (for Canvas or Moodle) also creates an announcement via the LMS API so it appears in both your app's feed and the institution's LMS. This dual-write pattern is what truly replaces Edmodo — your app is the engagement layer, the LMS is the institutional record.

For parent-teacher private messaging (another Edmodo staple), add a `messages` collection/table with `sender_id`, `recipient_id`, `content`, `sent_at`, and a `thread_id` linking to a course. Build a simple messaging UI in FlutterFlow with Firestore/Supabase real-time listeners.

```
// Firestore security rules for the social feed
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Feed posts — teachers write, all class members read
    match /feeds/{postId} {
      allow read: if request.auth != null
        && request.auth.uid in resource.data.allowed_readers;
      allow create: if request.auth != null
        && request.auth.token.role == 'teacher';
      allow update, delete: if request.auth != null
        && request.auth.uid == resource.data.author_id;
    }
    // Private messages — sender and recipient only
    match /messages/{messageId} {
      allow read, write: if request.auth != null
        && (request.auth.uid == resource.data.sender_id
            || request.auth.uid == resource.data.recipient_id);
    }
  }
}
```

**Expected result:** Your FlutterFlow app has a real-time class feed powered by Firebase or Supabase, with a 'New Post' flow for teachers and a real-time listener that updates the feed ListView instantly when new content is posted.

### 5. Test the full migration flow and verify no Edmodo references remain

With the replacement LMS integrated and the social feed rebuilt, do a complete end-to-end test of your FlutterFlow app before publishing.

Verify the authentication flow first: for Google Classroom, confirm the OAuth consent screen appears correctly on a physical device (it will NOT work in web preview), the correct education scopes are requested, and the access token is stored in App State successfully. For Canvas or Moodle, confirm the Cloud Function proxy returns real data when called from FlutterFlow.

Check the data binding on every screen: course lists should show real courses from your LMS, roster screens should show real enrolled students, and the social feed should show posts from your Firebase/Supabase backend in real time. Create a test post from a teacher account and verify it appears on a student account's feed without refreshing.

Run a search through your project's custom code, App Values, and any hardcoded strings for any reference to 'edmodo', 'api.edmodo.com', or any Edmodo URL — these must all be removed. There should be no code in your FlutterFlow project that attempts to contact any Edmodo endpoint.

Finally, test on both iOS and Android physical devices. For Google Classroom specifically, the OAuth flow requires platform-specific configuration (reversed client ID in Info.plist for iOS, SHA-1 fingerprint + google-services.json for Android) — verify that sign-in works on both platforms before publishing.

If you need help completing the migration or configuring the Cloud Function proxy for your specific LMS, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

**Expected result:** Your FlutterFlow app connects successfully to the chosen replacement LMS, displays real course and roster data, shows a live social feed, and contains no references to Edmodo in any code or configuration.

## Best practices

- Lead all user-facing content in your app with the active platform name (Google Classroom, Canvas, or Moodle) — never call it 'Edmodo replacement' in the UI, as this creates confusion for users who may not recognize the Edmodo brand.
- Always use a Cloud Function proxy for LMS credentials, regardless of which platform you choose — API tokens for Google (client secret), Canvas (bearer token), and Moodle (wstoken) all expose sensitive institutional data if embedded in Dart.
- Build the social feed component entirely in Firebase or Supabase rather than trying to replicate it through LMS API calls — native real-time listeners in FlutterFlow give you a faster, more reliable feed than polling an LMS API for new content.
- Store the LMS course IDs in your Firestore/Supabase feed documents so you can link feed posts back to specific courses, enabling per-class filtered views that replicate Edmodo's class-specific streams.
- Test OAuth-based authentication (Google Classroom path) exclusively on physical devices — FlutterFlow's web preview will not correctly render OAuth redirect flows, and skipping device testing is the most common cause of auth failures at launch.
- Add proper error handling in your Action Flows for the case where the Cloud Function proxy returns a non-200 status — show a user-friendly message rather than a silent failure when the LMS connection fails.
- For schools transitioning from Edmodo, provide an onboarding screen explaining the new platform and its benefits — many users may be unfamiliar with the replacement LMS and will drop off without clear context.
- Verify your chosen replacement platform's terms of service regarding mobile app access before launching — some institutional LMS contracts include restrictions on third-party app access that may require IT department approval.

## Use cases

### K-12 classroom companion app migrated from Edmodo to Google Classroom

A school that relied on Edmodo for class announcements and assignment tracking wants a mobile app for teachers and students. Using the Google Classroom migration path, FlutterFlow calls the Classroom API via a custom action using `google_sign_in`, displays course rosters and assignments, and stores class announcements in Firestore as a social feed that mimics the Edmodo posting experience.

Prompt example:

```
Build a teacher home screen showing their active Google Classroom classes, a feed of recent announcements per class, and a student roster. Add a 'Post announcement' form that writes to Firestore and optionally creates a Classroom announcement via the API.
```

### University LMS mobile front-end migrated to Canvas LMS

A university that switched from Edmodo to Canvas LMS wants a branded mobile app for students to check grades, see upcoming assignments, and read course announcements. FlutterFlow uses a Canvas REST API Group with a token sourced from a Cloud Function proxy, displaying course data and assignment due dates in a clean native UI.

Prompt example:

```
Create a student home screen with a ListView of enrolled courses, each showing the next assignment due date and a grade summary. Tapping a course opens an assignment list with completion status indicators.
```

### Parent-teacher communication app built on Moodle

A school running a self-hosted Moodle instance wants a FlutterFlow app where parents can see their child's course enrollments, grades, and teacher messages. The app connects to Moodle's Web Services API using the function-based `wsfunction` pattern through a Cloud Function proxy, and builds the parent-teacher messaging layer in Supabase's realtime database.

Prompt example:

```
Build a parent dashboard showing each child's enrolled Moodle courses with grade summaries, and a messaging tab that shows Moodle forum posts from teachers alongside a Supabase-backed direct-message thread.
```

## Troubleshooting

### API calls to Edmodo endpoints return errors or time out completely

Cause: Edmodo shut down permanently in September 2022. All Edmodo API endpoints (`api.edmodo.com` and related domains) are either unreachable or returning empty responses. There are no exceptions — the platform is fully defunct.

Solution: Stop attempting to connect to Edmodo. Follow this guide to migrate to Google Classroom, Canvas LMS, or Moodle. There is no workaround, no legacy API, and no alternative access path for Edmodo data or services.

### Google Classroom OAuth sign-in fails or shows a blank screen in FlutterFlow's web preview

Cause: OAuth 2.0 redirect-based authentication does not work inside FlutterFlow's browser-based web preview (iframe). The redirect flow gets blocked by the preview sandbox.

Solution: Test Google Classroom authentication exclusively on a physical device using the FlutterFlow mobile preview app, or compile and install a debug APK/IPA. OAuth works correctly in real native builds. Also verify that your Google Cloud Console OAuth client has the correct authorized redirect URI for your app's scheme (reversed client ID for iOS, SHA-1 fingerprint registered for Android).

### Canvas API calls return 401 Unauthorized from the Cloud Function proxy

Cause: The Canvas API token is either expired, incorrectly scoped, or stored incorrectly in the Cloud Function environment variables.

Solution: Log into Canvas, go to Account → Settings → Approved Integrations, and verify your access token still exists and has not expired. Regenerate it if needed, then update the `CANVAS_API_TOKEN` environment variable in your Firebase Cloud Function and redeploy. Also confirm the `CANVAS_BASE_URL` environment variable matches your exact Canvas instance URL (e.g. `https://yourschool.instructure.com`).

### Moodle API calls return HTTP 200 but the body contains `{"exception":...,"errorcode":"accessexception"}`

Cause: The Moodle Web Services token does not have the requested `wsfunction` added to its External service, or the External service does not have the 'REST protocol' enabled. Moodle returns HTTP 200 even for permission errors — the error is in the response body, not the HTTP status code.

Solution: Log into your Moodle admin panel, go to Site administration → Server → Web services → External services, find the service your token is associated with, and add the missing wsfunction to the service's function list. Also confirm that Site administration → Server → Web services → Overview shows both 'Enable web services' and 'Enable REST protocol' as ticked. After updating, retry the API call — no FlutterFlow changes are needed.

## Frequently asked questions

### Is Edmodo still available? Can I still use its API?

No. Edmodo permanently shut down all services in September 2022. The platform, all user accounts, all data, and all API endpoints are gone. Any documentation or tutorial describing an active Edmodo API is outdated. You cannot connect to Edmodo from FlutterFlow or any other platform — migration to an active replacement is the only path forward.

### Can I recover data from Edmodo to import into my new app?

No. Edmodo's data export service ended when the platform shut down in September 2022. There is no mechanism to retrieve historical class data, posts, assignments, or user records from Edmodo. Your migration means rebuilding from scratch on the new platform — rosters, course data, and historical content must be re-entered or re-imported from whatever local backups your institution maintained before the shutdown.

### Which Edmodo replacement is best for K-12 schools?

Google Classroom is the most widely adopted Edmodo replacement for K-12 environments and has the smoothest onboarding for schools already using Google Workspace for Education. It is free, requires no institutional license, and covers the core Edmodo use cases: class feeds, assignments, and rosters. Canvas LMS is a stronger choice if your district needs a full-featured gradebook and assignment management system, though it requires a license for most institutional deployments.

### How do I rebuild the Edmodo social feed in FlutterFlow?

None of the LMS replacement platforms offer a native mobile-first social feed through their APIs — that feature must be built in your app's own backend. Use Firestore (with real-time listeners) or Supabase Realtime to create a `feed_posts` collection linked to LMS course IDs. FlutterFlow's native Firestore and Supabase integrations support real-time streaming queries, so new posts appear instantly in the feed ListView without a page refresh.

### Does the Google Classroom integration work in FlutterFlow's web preview?

No — Google Classroom requires OAuth 2.0 authentication, and the OAuth redirect flow does not work inside FlutterFlow's iframe-based web preview. You must test the Google Classroom authentication on a physical device (iOS or Android) using the FlutterFlow mobile preview app or a compiled debug build. The rest of the app (feeds, course lists, roster display) can be previewed on web once you have a stored access token in App State.

---

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