Skip to main content
RapidDev - Software Development Agency
flutterflow-integrationsFlutterFlow API Call

WordPress

Connect FlutterFlow to WordPress using the WordPress REST API at /wp-json/wp/v2/. Public content reads (posts, pages, media) work as direct API Calls with no authentication — ideal for headless blog or news apps. Authenticated writes use Application Passwords proxied through Firebase Cloud Functions to keep credentials out of your app bundle.

What you'll learn

  • How to configure a FlutterFlow API Group targeting the WordPress /wp-json/wp/v2/ base URL
  • How to fetch posts with the ?_embed param to pull featured images in a single request
  • How to parse WordPress HTML content for display in Flutter using a Custom Widget
  • How to proxy Application Password authentication through Firebase Cloud Functions for write operations
  • How to implement pagination and pull-to-refresh for a WordPress content feed
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner15 min read30 minutesMedia & ContentLast updated July 2026RapidDev Engineering Team
TL;DR

Connect FlutterFlow to WordPress using the WordPress REST API at /wp-json/wp/v2/. Public content reads (posts, pages, media) work as direct API Calls with no authentication — ideal for headless blog or news apps. Authenticated writes use Application Passwords proxied through Firebase Cloud Functions to keep credentials out of your app bundle.

Quick facts about this guide
FactValue
ToolWordPress
CategoryMedia & Content
MethodFlutterFlow API Call
DifficultyBeginner
Time required30 minutes
Last updatedJuly 2026

Build a Headless WordPress App in FlutterFlow

WordPress ships a first-party REST API out of the box — no plugin required. Every WordPress site exposes posts, pages, media, categories, tags, and custom post types at /wp-json/wp/v2/, and public reads require zero authentication. That means you can build a fully functional headless news or blog app in FlutterFlow without writing a single line of backend code for the read path. The ?_embed query parameter is the key detail: it inlines the featured image and author data into the same post response, so your post card list loads in one round trip instead of making separate media requests per item.

The split comes when you need writes. WordPress uses Application Passwords (introduced in WordPress 5.6) — per-app tokens used as HTTP Basic Auth credentials. Since FlutterFlow compiles to a Flutter client running on the user's device, any secret placed in an API Call header is embedded in the app bundle and can be extracted. Application Passwords must be proxied through a backend like Firebase Cloud Functions or a Supabase Edge Function. The function holds the credential server-side and forwards authenticated requests to WordPress on behalf of the app.

One gotcha to check early: some managed hosts and WordPress security plugins (Wordfence, iThemes Security) disable or restrict the /wp-json endpoint, returning 401 or 404 even for public posts. Before you build, confirm the endpoint is reachable by visiting https://yoursite.com/wp-json/wp/v2/posts in a browser. WordPress is free and open-source to self-host; hosting costs vary by provider.

Integration method

FlutterFlow API Call

FlutterFlow connects to WordPress through its built-in REST API at /wp-json/wp/v2/. Public reads (posts, pages, categories, media) are direct API Calls requiring no secret key — making a read-only news or blog app genuinely beginner-level. Authenticated write operations (create/update/delete posts) use Application Passwords as HTTP Basic Auth, which must be routed through a Firebase Cloud Function or Supabase Edge Function to keep the credential out of the compiled app.

Prerequisites

  • A WordPress site (self-hosted or WordPress.com Business plan) with /wp-json/wp/v2/ accessible — verify in a browser before starting
  • A FlutterFlow project with at least one screen to display the content feed
  • For write operations: a WordPress user account with Editor or Administrator role to generate an Application Password
  • For write operations: a Firebase project (Blaze plan) or a Supabase project to host the proxy Cloud Function / Edge Function
  • Basic familiarity with FlutterFlow's API Calls panel and Data Types

Step-by-step guide

1

Verify the WordPress REST API is accessible

Before building anything in FlutterFlow, confirm that your WordPress site's REST API is publicly reachable. Open a browser and navigate to https://yoursite.com/wp-json/wp/v2/posts — you should see a JSON array of recent posts. If you get a 401 Unauthorized or 404 Not Found, you have a configuration issue to resolve first. Common causes: (1) a security plugin like Wordfence or iThemes Security has disabled REST API access for non-logged-in users — you'll need to whitelist the endpoint in the plugin settings; (2) the site is behind HTTP Auth (common on staging environments) — add the HTTP Auth credentials to every API Call header; (3) Pretty Permalinks are disabled in WordPress Settings → Permalinks, which breaks /wp-json routing — switch to any permalink structure other than 'Plain'. Once you can see the raw JSON in the browser, you're ready to build the API Group in FlutterFlow. Make a note of your site's base URL — you'll use it as the API Group base URL in the next step.

Pro tip: Add ?per_page=1 to the URL (e.g., /wp-json/wp/v2/posts?per_page=1) for a faster test — it fetches only the most recent post.

Expected result: Your browser displays a JSON array containing at least one post object with fields like id, title, content, excerpt, and _links.

2

Create an API Group in FlutterFlow for the WordPress REST API

In FlutterFlow, click API Calls in the left navigation panel. Click the + Add button and choose Create API Group. Name the group 'WordPress' and set the Base URL to https://yoursite.com/wp-json/wp/v2 — replace 'yoursite.com' with your actual WordPress domain. Leave authentication as 'None' for now (public reads require no auth header). Click Save to create the group. Next, add your first API Call inside this group: click + Add API Call, name it 'Get Posts', set the method to GET, and enter /posts as the endpoint path. In the Query Parameters tab, click + Add Parameter and add two parameters: (1) name '_embed', value '1' — this tells WordPress to include the featured media and author in the response so you avoid extra requests per post; (2) name 'per_page', type Integer, default '10' — controls how many posts are returned. Click Response & Test, paste a sample posts response from your browser test into the Response Body field, then click Get Reponse Fields to auto-generate JSON paths. FlutterFlow will extract paths like $.title.rendered, $.excerpt.rendered, $.id, and nested paths like $._embedded['wp:featuredmedia'][0].source_url for the featured image. Map these into a Data Type called 'WPPost' with fields: id (Integer), title (String), excerpt (String), featuredImageUrl (String), content (String). Click Test API Call to confirm it returns live data.

api_group_config.json
1{
2 "Group Name": "WordPress",
3 "Base URL": "https://yoursite.com/wp-json/wp/v2",
4 "Calls": [
5 {
6 "Name": "Get Posts",
7 "Method": "GET",
8 "Endpoint": "/posts",
9 "Query Params": {
10 "_embed": "1",
11 "per_page": "[variable:perPage]",
12 "page": "[variable:page]",
13 "categories": "[variable:categoryId]"
14 },
15 "JSON Paths": {
16 "id": "$[*].id",
17 "title": "$[*].title.rendered",
18 "excerpt": "$[*].excerpt.rendered",
19 "featuredImageUrl": "$[*]._embedded['wp:featuredmedia'][0].source_url",
20 "content": "$[*].content.rendered",
21 "slug": "$[*].slug"
22 }
23 }
24 ]
25}

Pro tip: The _embedded path uses single quotes inside brackets: $[*]._embedded['wp:featuredmedia'][0].source_url — include the quotes exactly or the JSON path won't resolve.

Expected result: The API Calls panel shows a 'WordPress' group with a 'Get Posts' call. Testing it returns a list of posts with titles, excerpts, and featured image URLs populated correctly.

3

Render WordPress HTML content using a Custom Widget

WordPress stores post content and excerpts as HTML strings in the content.rendered and excerpt.rendered fields. A standard Flutter Text widget will display the raw HTML tags (like <p>, <strong>, <img>) as literal text rather than rendering them. To display formatted post bodies, you need an HTML rendering Custom Widget. In FlutterFlow, go to Custom Code in the left nav, click + Add, and choose Widget. Name it 'HtmlContentWidget'. In the Dependencies field, add flutter_html as a pub.dev package (current version — check pub.dev for the latest). Paste the Dart code below. This widget accepts a single String parameter called htmlContent and renders it with flutter_html's Html widget, which handles headings, paragraphs, bold, italic, links, and inline images. After creating the widget, go to your post detail screen. Add the HtmlContentWidget from the Widget Palette under Custom Widgets. In the Properties panel, bind the htmlContent parameter to your WPPost.content field from your Data Type or page state. Set a reasonable width (Match Parent) and let the height be dynamic. Important: Custom Widgets do not render in FlutterFlow's web Test Mode — you must use Run mode or test on a real device or emulator to see the HTML rendered correctly. For post cards showing just an excerpt, you can use a simpler approach: strip the HTML tags using a Dart Custom Action (replace all <[^>]+> with an empty string) and display the result in a standard Text widget.

html_content_widget.dart
1import 'package:flutter/material.dart';
2import 'package:flutter_html/flutter_html.dart';
3
4class HtmlContentWidget extends StatelessWidget {
5 const HtmlContentWidget({
6 super.key,
7 required this.htmlContent,
8 this.width,
9 this.height,
10 });
11
12 final String htmlContent;
13 final double? width;
14 final double? height;
15
16 @override
17 Widget build(BuildContext context) {
18 return SizedBox(
19 width: width,
20 height: height,
21 child: SingleChildScrollView(
22 child: Html(
23 data: htmlContent,
24 style: {
25 'body': Style(
26 fontSize: FontSize(16.0),
27 fontFamily: 'Roboto',
28 color: Theme.of(context).textTheme.bodyLarge?.color,
29 ),
30 'h1': Style(fontSize: FontSize(24.0)),
31 'h2': Style(fontSize: FontSize(20.0)),
32 'p': Style(margin: Margins.only(bottom: 12.0)),
33 },
34 ),
35 ),
36 );
37 }
38}

Pro tip: For excerpt previews on cards, create a Custom Action that strips HTML tags (htmlContent.replaceAll(RegExp(r'<[^>]+>'), '')) — lighter than loading the full flutter_html widget in every list item.

Expected result: The HtmlContentWidget appears in your Custom Widgets list. When bound to a WordPress post's content.rendered field on device, it renders formatted text with proper paragraphs, headings, and inline images.

4

Proxy authenticated writes via a Firebase Cloud Function

If your app needs to create, update, or delete WordPress posts — not just read them — you'll use WordPress Application Passwords for authentication. Application Passwords are per-app tokens generated in WordPress Admin → Users → Your Profile → scroll to Application Passwords. Enter a name for the app, click Add New Application Password, and copy the generated password immediately (it's only shown once). The credential is used as HTTP Basic Auth: the header is Authorization: Basic base64(username:application_password). Since this credential must never be embedded in the Flutter app bundle, route authenticated requests through a Firebase Cloud Function. The function stores the WordPress username and Application Password as environment secrets (set via the Firebase Console → Functions → Configuration, or using firebase functions:secrets:set in the Firebase CLI). FlutterFlow calls your Cloud Function endpoint instead of WordPress directly — passing the post data as a JSON body. The function builds the WordPress API request with the Authorization header attached and forwards it. In FlutterFlow, add a new API Call in the WordPress group named 'Create Post (via proxy)'. Set the method to POST, and the endpoint to your Cloud Function URL (e.g., https://us-central1-your-project.cloudfunctions.net/wpProxy). Add a JSON body variable containing the post fields. This way, the Application Password never touches the client. If you'd rather skip building the proxy yourself, RapidDev's team builds FlutterFlow integrations like this every week — free scoping call at rapidevelopers.com/contact.

index.js
1// Firebase Cloud Function (Node.js) — index.js
2const { onRequest } = require('firebase-functions/v2/https');
3const { defineSecret } = require('firebase-functions/params');
4const fetch = require('node-fetch');
5
6const WP_USERNAME = defineSecret('WP_USERNAME');
7const WP_APP_PASSWORD = defineSecret('WP_APP_PASSWORD');
8const WP_BASE_URL = 'https://yoursite.com/wp-json/wp/v2';
9
10exports.wpProxy = onRequest(
11 { secrets: [WP_USERNAME, WP_APP_PASSWORD] },
12 async (req, res) => {
13 res.set('Access-Control-Allow-Origin', '*');
14 if (req.method === 'OPTIONS') {
15 res.set('Access-Control-Allow-Methods', 'POST');
16 res.set('Access-Control-Allow-Headers', 'Content-Type');
17 return res.status(204).send('');
18 }
19
20 const credentials = Buffer.from(
21 `${WP_USERNAME.value()}:${WP_APP_PASSWORD.value()}`
22 ).toString('base64');
23
24 const { endpoint, method, body } = req.body;
25 const wpResponse = await fetch(`${WP_BASE_URL}${endpoint}`, {
26 method: method || 'POST',
27 headers: {
28 Authorization: `Basic ${credentials}`,
29 'Content-Type': 'application/json',
30 },
31 body: JSON.stringify(body),
32 });
33
34 const data = await wpResponse.json();
35 return res.status(wpResponse.status).json(data);
36 }
37);

Pro tip: Set your WordPress secrets using the Firebase CLI: firebase functions:secrets:set WP_USERNAME and firebase functions:secrets:set WP_APP_PASSWORD — never paste them in plaintext in the Firebase Console or your code.

Expected result: The Cloud Function is deployed and callable. When FlutterFlow sends a POST to the function URL with post data, the function creates a new draft post in WordPress and returns the created post's ID.

5

Add pagination and pull-to-refresh to the post list

WordPress REST API supports cursor-based pagination via the page and per_page query parameters. For a FlutterFlow ListView showing blog posts, you'll want to implement pagination so the app doesn't fetch all posts at once — especially for sites with hundreds of entries. In your Get Posts API Call, ensure the page variable is defined with a default value of 1 (Integer type). In your ListView screen, add a Page State variable called currentPage (Integer, initial value 1). Use an Action Flow on your ListView's scroll position or a 'Load More' button: when triggered, increment currentPage by 1, then call the Get Posts API with the updated page value, and append the results to your existing list using a Combine action. For pull-to-refresh, wrap your ListView in a RefreshIndicator widget (available in FlutterFlow's widget palette). On the onRefresh callback, reset currentPage to 1 and re-fetch the posts — this replaces the existing list data. Add the per_page variable to the API Call and set it to 10 or 20 items based on your design. WordPress also returns total post count and total pages in the response headers (X-WP-Total and X-WP-TotalPages), which you can use to show a 'no more posts' indicator when you've reached the end of the list. Check the Headers tab in your API Call Response to read these values.

Pro tip: WordPress returns X-WP-TotalPages in the response headers. Check this value against your currentPage to hide the 'Load More' button when all pages are loaded — preventing unnecessary API calls.

Expected result: The post list loads 10 items initially. Scrolling to the bottom and tapping 'Load More' fetches the next page and appends the posts. Pulling down from the top of the list refreshes and shows the latest posts.

Common use cases

Mobile news app pulling posts from a WordPress blog

A FlutterFlow app that displays a paginated feed of WordPress blog posts with featured images, categories, and excerpts. Tapping a card opens the full post rendered via an HTML widget. The app supports pull-to-refresh and category filtering via query params.

FlutterFlow Prompt

Build a news feed screen in FlutterFlow that fetches the latest 10 WordPress posts from my site, shows the featured image, title, and excerpt in a card list, and opens the full post body on tap.

Copy this prompt to try it in FlutterFlow

Content management companion app for WordPress authors

An internal FlutterFlow app that lets content authors create draft posts, update titles and body text, and change post status — all authenticated via Application Passwords proxied through Firebase. Read operations load the post list directly; write operations go through the secure proxy.

FlutterFlow Prompt

Build a FlutterFlow app that lets me log in and create or edit WordPress posts from my phone. Show a list of my recent posts and a form to create a new draft.

Copy this prompt to try it in FlutterFlow

Product catalog app powered by WordPress custom post types

A FlutterFlow catalog app that reads a custom post type (e.g., 'products') from a WordPress site using the REST API endpoint /wp-json/wp/v2/products. Each product card shows the featured image, title, and custom field values, pulled via ACF's REST API extension.

FlutterFlow Prompt

Create a FlutterFlow product catalog that fetches items from a WordPress custom post type called 'products', shows thumbnails and prices, and lets users filter by category.

Copy this prompt to try it in FlutterFlow

Troubleshooting

GET /wp-json/wp/v2/posts returns 401 Unauthorized or 404 Not Found for public posts

Cause: A WordPress security plugin (Wordfence, iThemes Security, All-In-One Security) has restricted REST API access to authenticated users only, or the site is on a staging environment with HTTP Basic Auth protecting the whole site.

Solution: In your security plugin settings, find the REST API section and disable 'Restrict REST API access to logged-in users.' For Wordfence, go to Wordfence → All Options → General Options. For staging HTTP Auth, add an Authorization header with the staging credentials to your FlutterFlow API Group's shared headers. Alternatively, confirm Pretty Permalinks are enabled in WordPress → Settings → Permalinks (any option other than 'Plain').

Post content displays raw HTML tags like <p>, <strong>, and <img src=...> as literal text in the app

Cause: WordPress content.rendered and excerpt.rendered fields contain HTML strings. A standard Flutter Text widget does not render HTML — it displays the markup literally.

Solution: Use the flutter_html Custom Widget (see Step 3). For excerpt snippets on post cards, use a Custom Action that strips HTML tags: htmlContent.replaceAll(RegExp(r'<[^>]+>'), '') before binding to a Text widget. The flutter_html widget must be tested on a real device or emulator — it does not render in FlutterFlow's web Test Mode.

typescript
1// Strip HTML tags in a Custom Action
2String stripHtml(String htmlContent) {
3 return htmlContent.replaceAll(RegExp(r'<[^>]+>'), '').trim();
4}

Featured image is missing or the _embedded path returns null in the JSON

Cause: The ?_embed=1 query parameter was not added to the API Call, or the post has no featured image set in WordPress, or the JSON path for the embedded media is wrong.

Solution: Confirm the Query Parameter _embed is set to '1' (string '1', not integer) in your API Call's Query Parameters tab. In the JSON path, use $[*]._embedded['wp:featuredmedia'][0].source_url — include the single quotes around wp:featuredmedia. In FlutterFlow, handle nullable image URLs by setting a fallback placeholder in the Image widget's Not Set state.

Authenticated API calls (create/update post) return 403 Forbidden or 401 Unauthorized

Cause: The Application Password was passed directly in the FlutterFlow API Call header (shipping it in the app bundle) but the encoding is wrong, or the WordPress user role does not have post-creation permissions.

Solution: Move the Application Password to a Firebase Cloud Function proxy (see Step 4). The function must base64-encode username:application_password and set the Authorization: Basic header. Confirm the WordPress user has the 'Editor' or 'Author' role with permission to publish posts. Application Passwords require WordPress 5.6+ and must be enabled — some hosts disable them via the disable_application_passwords filter.

Best practices

  • Always test the /wp-json/wp/v2/ endpoint in a browser before configuring FlutterFlow — security plugins blocking the API are the #1 cause of failed integrations.
  • Use ?_embed=1 on every post list request to include featured images and author data in one call — avoids N+1 requests that slow down the post feed.
  • Never place Application Passwords or any WordPress authentication credential in a FlutterFlow API Call header — proxy all write operations through Firebase Cloud Functions or Supabase Edge Functions.
  • Use the per_page parameter (default 10) and implement pagination rather than fetching all posts at once — WordPress sites often have thousands of posts.
  • Create a FlutterFlow Data Type (e.g., WPPost) to hold the parsed post fields — this lets you bind data cleanly to ListViews and detail screens without repeatedly re-parsing JSON paths.
  • Handle the case where a post has no featured image by setting a placeholder in your Image widget — not all WordPress posts have featured media set.
  • Strip HTML tags from excerpt.rendered for list card previews using a Custom Action — reserve the full flutter_html widget for the detail screen to keep list scroll performance smooth.
  • Check the X-WP-TotalPages response header to implement a proper end-of-list indicator and avoid making empty page requests.

Alternatives

Frequently asked questions

Do I need a WordPress plugin to use the REST API in FlutterFlow?

No. The WordPress REST API has been built into WordPress core since version 4.7. You can start making GET requests to /wp-json/wp/v2/posts immediately with no additional plugins. The only plugins you might consider are ACF (Advanced Custom Fields) with its REST API support for custom field data, or WP REST Cache to improve performance for high-traffic apps.

Can I connect FlutterFlow to WordPress.com (not self-hosted)?

WordPress.com restricts REST API access differently from self-hosted WordPress. For WordPress.com sites, you'll use the WordPress.com REST API (v1.1 at public-api.wordpress.com/rest/v1.1/sites/{site}/posts) with a different base URL. Application Passwords work on WordPress.com Business and Commerce plans. The /wp-json/wp/v2/ endpoint described in this guide is specific to self-hosted WordPress installations.

Can FlutterFlow display the WordPress admin dashboard?

FlutterFlow is not designed to embed the WordPress admin interface. You're building a native Flutter app that communicates with WordPress data via the REST API. For content management from the app, you'd build custom screens in FlutterFlow that call the authenticated write endpoints (proxied through Cloud Functions), giving your team a tailored mobile editing experience rather than trying to wrap the web admin.

Will the flutter_html widget work on web builds of my FlutterFlow app?

The flutter_html package works on both mobile and web targets in Flutter. However, Custom Widgets do not render in FlutterFlow's in-browser Test Mode (the preview canvas) — they only render correctly in Run mode, on a real device, or in a production web build. Use Run mode or deploy a web build to verify HTML rendering before publishing.

How do I handle WordPress posts with custom post types in FlutterFlow?

Custom post types registered with the REST API (using show_in_rest: true in register_post_type) are accessible at /wp-json/wp/v2/{custom_post_type_slug}. For example, if you have a 'products' post type, you'd add a second API Call in your FlutterFlow WordPress group with endpoint /products. Parse the response into a separate Data Type and bind it to your product list screen.

RapidDev

Talk to an Expert

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

Book a free consultation

Integrations are where projects stall

We wire FlutterFlow integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

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.