Connect Bubble to Framer using the API Connector plugin to sync content between Framer's CMS REST API and your Bubble app. Place your Framer API token in a Private shared header — it stays server-side and never reaches the browser. The split-stack pattern keeps Framer's design-heavy marketing pages separate from Bubble's authenticated SaaS backend, with Bubble workflows managing Framer CMS items via POST and PATCH calls.
| Fact | Value |
|---|---|
| Tool | Framer |
| Category | DevOps & Tools |
| Method | Bubble API Connector |
| Difficulty | Intermediate |
| Time required | 60–90 minutes |
| Last updated | July 2026 |
Split-stack architecture: Framer for marketing, Bubble for the product
The most common Bubble + Framer setup is a split-stack product: Framer handles your public marketing site — the landing page, blog, pricing page, feature showcase — while Bubble powers the authenticated SaaS backend behind the login wall. This split works because Framer excels at design-heavy, SEO-friendly static publishing, while Bubble excels at data-driven web applications with complex logic and user-specific views.
The practical integration between these two systems has two layers. First, Bubble admins can manage Framer CMS content without ever logging into Framer — a Bubble internal dashboard posts directly to the Framer CMS REST API, updating announcement banners, blog posts, or feature descriptions. Second, Framer can notify Bubble when a CMS item is published, letting Bubble react — for example, by sending a notification email or updating a database record.
Bubble's API Connector is the right tool for both directions. All calls exit from Bubble's servers, so your Framer API token stays in a Private header and is never exposed in browser network traffic. The token only becomes relevant on Framer's end when your server makes the call — which is exactly how it should work for a service-level API key.
One important architectural boundary to understand: Framer's runtime (CSS animations, smart components, breakpoint layouts) is entirely client-side code running on Framer's hosting infrastructure. You cannot embed a live Framer component inside a Bubble page — the two frontends are separate domains. Keep Framer as your public domain or subdomain (e.g., www.yourproduct.com) and Bubble as your app domain (e.g., app.yourproduct.com).
Integration method
API Connector targeting Framer's CMS REST API (https://api.framer.com/store/api/v1) with a Bearer token stored in a Private shared header — all calls are server-side proxied by Bubble.
Prerequisites
- A Bubble app on any plan for API Connector calls (reading and writing to Framer CMS); Bubble Starter paid plan or above if you want to receive inbound Framer webhooks via Backend Workflows
- A Framer account on the Basic plan ($15/month) or above — CMS API access is not available on the Free or Mini plans
- A Framer API token generated from Project Settings → Integrations → API
- Your Framer CMS Collection IDs — visible in the CMS panel of your Framer project or in the API documentation for your project
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)
Step-by-step guide
Generate a Framer API token and find your Collection IDs
Before configuring anything in Bubble, collect the two pieces of information you need from Framer: your API token and the Collection ID of the CMS collection you want to manage. To generate an API token, open your Framer project, click the project name in the top-left to open Project Settings, then navigate to the Integrations tab. Scroll to the API section and click 'Generate token'. Framer will display a token string starting with a long alphanumeric sequence — copy it immediately and store it somewhere secure (a password manager, not a plain text file). Framer only shows the token once; if you lose it, you must generate a new one. To find your Collection ID, navigate to the CMS panel in Framer (click the CMS icon in the left sidebar). Click on the collection you want to manage from Bubble. Look at the URL in your browser — it will contain a path segment that looks like `/cms/{collectionId}`. Alternatively, make a test API call to `https://api.framer.com/store/api/v1/collections` using your token to list all collections and their IDs in a JSON response. Note: Framer CMS API access is gated behind the Basic plan ($15/month) or above. If your Framer project is on the Free or Mini plan, API calls to `/collections/{id}/items` will return a 403 Forbidden error. Upgrade your Framer plan before proceeding if needed.
1GET https://api.framer.com/store/api/v1/collections2Authorization: Bearer your-framer-api-token-herePro tip: Keep a note of both the Collection ID and the field names in your Framer CMS collection — these field names must match exactly in your Bubble API Connector POST body. Framer field names are case-sensitive.
Expected result: You have your Framer API token saved securely and have noted the Collection ID of the CMS collection you want to manage from Bubble.
Configure the API Connector with a Private Framer token header
In your Bubble editor, click the Plugins tab in the left sidebar. Click 'Add plugins', type 'API Connector' in the search box, and install the API Connector by Bubble (it is free). Once installed, click 'API Connector' in your Plugins list to open the configuration panel. Click 'Add another API' to create a new API group. Name it 'Framer CMS'. In the Shared headers section of this API group, click 'Add header'. In the Key field type `Authorization` and in the Value field type `Bearer ` followed by your Framer API token — the full value should look like `Bearer frm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. Check the 'Private' checkbox to the right of this header row. This checkbox is critical: it ensures Bubble's servers never expose the header value in client-side network requests, logs visible to users, or Bubble's debugger. The token stays entirely on Bubble's server side. Leave the Authentication dropdown set to 'None or self-handled' since you are handling auth manually via the header. Now click 'Add another call' to create your first API call. Name it 'List CMS Items'. Set the type to GET. In the URL field enter: `https://api.framer.com/store/api/v1/collections/YOUR_COLLECTION_ID/items` — replace YOUR_COLLECTION_ID with the actual Collection ID you noted in the previous step. Set the 'Use as' dropdown to 'Data' since this call returns a list of CMS items for display. This tells Bubble to treat the response fields as a data type you can bind to Repeating Groups and text elements.
1{2 "method": "GET",3 "url": "https://api.framer.com/store/api/v1/collections/<collection_id>/items",4 "headers": {5 "Authorization": "Bearer <framer_api_token - Private>"6 }7}Pro tip: If you have multiple Framer CMS collections (blog posts, case studies, team members), create a separate 'Add another call' for each collection ID within the same 'Framer CMS' API group — they all share the same Private Authorization header.
Expected result: The API Connector shows a 'Framer CMS' API group with a Private Authorization shared header and a 'List CMS Items' GET call configured.
Initialize the call to detect Framer CMS item field types
The initialize call is how Bubble learns the shape of Framer's response — it makes one real API request and maps the returned fields into Bubble data types you can use in Workflows and UI bindings. This step is mandatory; skipping it means your call has no fields and cannot be used in the Bubble editor. Click the 'Initialize call' button next to your 'List CMS Items' GET call. A panel will appear asking for test values for any dynamic parameters. Since this GET call has no dynamic parameters (the collection ID is hardcoded in the URL), click 'Send' directly. Bubble will make the actual API request to Framer using your Private token and display the response. If the call succeeds, you will see the Framer CMS items array with your collection's fields — for example, title (text), slug (text), body (text), published_date (date), hero_image (URL). Important: The initialize call only works if your Framer CMS collection has at least one published item. If the collection is empty, the response will be an empty array and Bubble will detect no fields. Add at least one real or placeholder item in Framer CMS before running Initialize. Review each detected field and confirm the field types make sense. Bubble typically detects text fields as 'Text' and ISO date strings as 'Date' — but verify date fields specifically, as they sometimes come through as 'Text' if the format is unusual. Click the type dropdown next to each field to change it if needed. Click 'Save' once all fields look correct. The detected field set becomes the 'Framer CMS Items' data type in your Bubble editor, available for binding in Repeating Groups, text expressions, and Workflow conditions.
Pro tip: If you change your Framer CMS collection schema later (add or remove fields), come back to this call in the API Connector and click 'Initialize call' again to refresh the detected field types. Bubble does not auto-detect schema changes.
Expected result: The initialize call returns HTTP 200, Bubble detects your Framer CMS item fields (title, slug, body, etc.), and the call is available as a data source in your Bubble editor.
Create Bubble Workflow actions to update Framer CMS items
Now build the write side of the integration: Bubble Workflows that create or update Framer CMS items via POST and PATCH calls. Click 'Add another call' in your Framer CMS API group to create the create call. Name it 'Create CMS Item'. Set the type to POST and the URL to `https://api.framer.com/store/api/v1/collections/YOUR_COLLECTION_ID/items`. In the Body section, set the body type to 'JSON body'. Enter the JSON structure matching your Framer CMS collection's fields with dynamic placeholders for the values: ```json { "fields": { "title": "<item_title>", "slug": "<item_slug>", "body": "<item_body>" } } ``` The exact field names inside `fields` must match your Framer CMS collection field names exactly (case-sensitive). Set 'Use as' to 'Action'. Click 'Initialize call', fill in test values for each dynamic field, and send. A successful response returns the newly created CMS item object with its Framer-assigned ID. For a PATCH (update) call, create another call named 'Update CMS Item', set type to PATCH, and use the URL: `https://api.framer.com/store/api/v1/collections/YOUR_COLLECTION_ID/items/<item_id>` — where item_id is a dynamic field you will populate at runtime from the Bubble database record that tracks each Framer item's ID. Once both calls are initialized, go to the Workflow editor. Add a workflow to a button click or form submission event. Click 'Add an action' → Plugins → 'Framer CMS - Create CMS Item'. Map the dynamic parameters to Bubble input values — for example, item_title = Input Title's value, item_slug = Input Title's value formatted as a URL-safe slug. RapidDev's team has connected dozens of Bubble admin dashboards to third-party CMS systems — if you need help structuring your admin UI or mapping complex data, book a free scoping call at rapidevelopers.com/contact.
1{2 "method": "POST",3 "url": "https://api.framer.com/store/api/v1/collections/<collection_id>/items",4 "headers": {5 "Authorization": "Bearer <framer_api_token - Private>",6 "Content-Type": "application/json"7 },8 "body": {9 "fields": {10 "title": "<item_title>",11 "slug": "<item_slug>",12 "body": "<item_body>"13 }14 }15}Pro tip: Store the Framer CMS item ID returned by the POST call in your Bubble database — create a data type field like 'framer_item_id' (Text) on the relevant Bubble Thing. You will need this ID for PATCH (update) and DELETE calls later.
Expected result: Clicking your Bubble button creates a new CMS item in Framer. You can verify it in Framer's CMS panel within seconds of the Workflow running.
Set up a Bubble Backend Workflow to receive Framer CMS webhooks (optional — paid plan required)
If you want Bubble to react when a Framer editor publishes content, you can configure a Framer webhook that fires to a Bubble Backend Workflow endpoint. This requires a paid Bubble plan (Starter or above) since Backend Workflows (API Workflows) are not available on the Bubble Free plan. In your Bubble editor, go to Settings (gear icon) → API tab. Enable 'This app exposes a Workflow API' toggle. Then navigate to the Backend Workflows section — click the 'Backend workflows' link that appears in the left panel of the editor or access it via the dropdown menu next to your app name. Click 'Add a new API workflow'. Name it 'Framer CMS Published'. Enable the option 'This workflow can be run without authentication' — Framer's webhook sender cannot pass your Bubble API token, so this endpoint must be publicly accessible. Click 'Detect request data' — Bubble will display a listener URL and wait for an incoming webhook. In Framer, open Project Settings → Integrations → Webhooks. Add a new webhook and paste your Bubble Backend Workflow detection URL. Set the trigger to 'CMS item published' or the equivalent event in your Framer version. Framer will send a test payload to the detection URL. Bubble will detect the request body fields — typically including the item ID, collection ID, and published fields. Click 'Save' to confirm the detected schema. Drop the `/initialize` suffix from the URL before saving it in Framer's webhook settings — the detect URL has an `/initialize` path for one-time schema detection; the production URL does not. Now build the workflow body: add steps after the trigger to create a Bubble database record, send a notification, or call another API based on the webhook payload. The detected fields (item_id, collection_id, etc.) are available as dynamic values in each step.
1{2 "endpoint": "https://yourapp.bubbleapps.io/api/1.1/wf/framer-cms-published",3 "trigger": "CMS item published",4 "sample_payload": {5 "item_id": "frm_item_abc123",6 "collection_id": "frm_col_xyz789",7 "slug": "my-blog-post",8 "title": "My Blog Post",9 "published_at": "2026-07-10T12:00:00Z"10 }11}Pro tip: After setting up the Backend Workflow, test it by publishing a CMS item in Framer and checking Bubble's Logs tab (left sidebar) to confirm the workflow ran and received the expected payload fields.
Expected result: Publishing a CMS item in Framer triggers your Bubble Backend Workflow. The workflow runs and the Logs tab shows the received payload with the item's fields.
Test end-to-end and understand the publish gap
With both directions configured, run an end-to-end test to validate the full flow and understand the most important architectural nuance of the Framer CMS API. For the Bubble → Framer direction: trigger your 'Create CMS Item' Workflow from the Bubble preview. Open your Framer project → CMS panel → your collection. The new item should appear within a few seconds marked as 'Draft' or 'Staged' but NOT yet visible on your live Framer site. This is the critical behaviour to understand: updating a Framer CMS item via the API does NOT automatically publish it to the live site. The item exists in the CMS but Framer still requires a manual or scheduled Publish to push changes live. As of the current Framer API version, there is no programmatic publish endpoint — you cannot trigger a site publish via the API. This means your workflow is: Bubble updates content → content queues in Framer CMS → Framer editor clicks Publish → live site updates. If your team needs content updates to go live without a manual Framer publish step, consider an alternative architecture: instead of using Framer CMS for the dynamic content, fetch the content directly from Bubble's data via a public API endpoint and display it on the Framer page using Framer's HTTP variables (Connect panel → Variables → Add API) — this way Framer always shows live Bubble data without a separate publish step. For the Framer → Bubble direction (if configured): publish a CMS item in Framer and verify the Bubble Backend Workflow ran by checking Logs tab → Workflow logs. Confirm the payload fields match what you set up during detection. Check your Bubble Logs tab for WU (Workload Unit) consumption — each API Connector call to Framer consumes WU on Bubble's post-2023 pricing. For apps that update Framer CMS frequently (more than a few times per hour), monitor your WU budget in the Bubble dashboard and consider batching updates if needed.
Pro tip: Consider adding a 'Last synced to Framer' date/time field to your relevant Bubble data type and updating it each time a successful Framer CMS call runs. This gives your admin team visibility into which records are in sync.
Expected result: Bubble Workflow creates a Framer CMS item, visible in Framer's CMS panel. You understand that a manual Framer Publish is still required before the change appears on the live site. Backend Workflow (if configured) receives Framer webhook events correctly.
Common use cases
Manage Framer CMS content from a Bubble admin dashboard
Build an internal Bubble admin panel where your team can draft, edit, and push content updates to your Framer marketing site — without logging into Framer. Button clicks in Bubble trigger API Connector calls that POST or PATCH items in the Framer CMS, so non-technical team members can update announcement banners, pricing tiers, or blog posts from a familiar Bubble data entry form.
When the 'Publish Announcement' button is clicked, call the Framer CMS API to create a new CMS item in the Announcements collection with title = Input Announcement Title's value, body = Input Body's value, and published_date = today's date formatted as an ISO string.
Copy this prompt to try it in Bubble
Sync Bubble user data to Framer CMS for a public directory
When a Bubble user opts into a public directory listing (by checking a 'List me publicly' checkbox), automatically create or update their profile as a Framer CMS item — so the public-facing Framer site shows an up-to-date member directory without any manual content management.
When a User's 'public_listing' field is set to true, call the Framer CMS API to POST a new item to the Members collection with name = User's display name, bio = User's bio field, and avatar_url = User's profile photo URL.
Copy this prompt to try it in Bubble
React to Framer content publishes inside Bubble
Set up a Bubble Backend Workflow as a webhook receiver so that when a Framer editor publishes a new CMS item, Bubble automatically triggers a downstream action — for example, sending a notification email to subscribers, logging the publish event in a Bubble database table, or triggering a Zapier/Make workflow via another API call.
When the Framer CMS webhook fires to the Bubble Backend Workflow URL, detect the item slug and collection name from the payload, create a PublishLog record in Bubble's database with those values and a timestamp, and send a notification email to the content team.
Copy this prompt to try it in Bubble
Troubleshooting
API Connector initialize call returns 403 Forbidden when calling Framer CMS endpoints
Cause: Your Framer project is on the Free or Mini plan, which does not include CMS API access. The Basic plan ($15/month) is the minimum plan that unlocks the CMS REST API.
Solution: Log into Framer, open your project, go to Project Settings → Plans, and upgrade to the Basic plan or above. After upgrading, return to Bubble and re-run the initialize call — the 403 should resolve immediately.
Initialize call returns HTTP 200 but Bubble detects no fields (empty field list)
Cause: Your Framer CMS collection is empty — there are no published items to return, so the response is an empty array and Bubble cannot infer the schema from it.
Solution: Add at least one real or placeholder item to your Framer CMS collection and publish it. Then return to the API Connector and run Initialize call again — Bubble will now detect the fields from the non-empty response.
POST to create a CMS item returns 422 Unprocessable Entity or 'invalid fields' error
Cause: The field names in your JSON body do not match the exact field names in the Framer CMS collection, or a required field is missing. Framer CMS field names are case-sensitive.
Solution: Open your Framer project → CMS panel → the relevant collection → click the gear icon or column headers to see the exact machine-readable field names (not the display labels). Update the JSON body in your Bubble API Connector call to use these exact names. Required fields must always be included even if empty.
1{2 "fields": {3 "title": "<item_title>",4 "slug": "<item_slug>"5 }6}Backend Workflow for Framer webhooks is not firing when CMS items are published in Framer
Cause: Either the Backend Workflow option 'This workflow can be run without authentication' is not enabled, the Framer webhook URL is using the /initialize detection URL instead of the production URL, or the Bubble app is on the Free plan which does not support Backend Workflows.
Solution: Check three things: (1) In your Backend Workflow settings, confirm 'This workflow can be run without authentication' is enabled. (2) In Framer's webhook settings, confirm the URL does not end in /initialize — remove that suffix to use the production endpoint. (3) Confirm your Bubble app is on a paid Starter plan or above. Free plan apps cannot expose Backend Workflow endpoints.
The Framer API call configuration shows 'There was an issue setting up your call' during initialize
Cause: The API token is missing or incorrectly formatted in the shared header, or the collection ID in the URL does not exist in your Framer account.
Solution: Verify the Authorization header value starts with 'Bearer ' (with a space before the token). Verify the collection ID is correct by listing all collections at https://api.framer.com/store/api/v1/collections. Regenerate the Framer API token if it was recently invalidated.
Best practices
- Always mark the Framer API token as Private in the API Connector shared header — even though the token is not as sensitive as a database password, keeping it server-side prevents it from appearing in Bubble's Logs tab or browser network requests.
- Store the Framer CMS item ID returned by POST calls in your Bubble database (as a Text field on the relevant data type) so you can reference the item for PATCH and future updates without needing to search by slug.
- Add a 'framer_published_at' timestamp field to your Bubble data type and update it only when a Framer webhook confirms a publish event — this lets your admin dashboard distinguish between 'staged in Framer CMS' and 'live on the Framer site'.
- Do NOT attempt to embed Framer components or pages inside a Bubble page using an iframe — Framer's CSS animations and responsive breakpoints break inside iframes, and authentication state cannot be shared between the two domains.
- Keep Framer as a separate domain or subdomain from your Bubble app (e.g., www.yourproduct.com for Framer, app.yourproduct.com for Bubble) to maintain clear routing and avoid cookie/auth conflicts.
- If your Bubble app updates Framer CMS items frequently, monitor your WU consumption in the Bubble dashboard — each API Connector call consumes Workload Units. For bulk updates, consider batching multiple field changes into a single PATCH call instead of making one call per field change.
- Set up Privacy Rules on any Bubble data types that contain Framer API responses — go to Data tab → Privacy → add rules restricting which fields of the Framer content data type are visible to different user roles.
- Test your API Connector configuration by running Initialize call with real data before building Workflows — a successful initialize confirms authentication, URL, and schema detection all work correctly before you invest time in Workflow logic.
Alternatives
Figma is a design file tool, not a live hosting platform — the Figma API gives you access to design file structure and asset exports, not live CMS content. Use Figma if you need to extract design tokens or assets for your Bubble app's visual reference; use Framer if you need to manage live marketing site content from Bubble.
WordPress with WP REST API is a more established content platform with a richer API for complex editorial workflows, custom taxonomies, and media management. Use WordPress if your team needs a full editorial CMS with roles and review workflows; use Framer if you prioritize design quality and animation on the marketing site.
Notion's API can serve as a lightweight CMS for Bubble via API Connector — pages become content items. Notion is more flexible for document-style content and team collaboration, while Framer CMS is purpose-built for structured web content with tight design integration. Use Notion for knowledge bases and internal docs; use Framer for polished public marketing pages.
Frequently asked questions
Can I publish a Framer site from a Bubble Workflow?
Not directly — as of the current Framer API version, there is no API endpoint to trigger a site publish. Your Bubble Workflow can create and update Framer CMS items via the API, but making those changes live on the Framer site still requires a manual Publish click in the Framer editor. Plan your workflow so content editors understand this two-step process: update in Bubble, then publish in Framer.
Which Framer plan do I need to use the CMS API?
You need the Framer Basic plan ($15/month) or above. The Free and Mini plans do not include CMS API access — calls to the /collections endpoint will return 403 Forbidden. Check your current Framer plan in Project Settings → Plans before setting up the Bubble API Connector.
Does my Bubble app need a paid plan to connect to Framer?
For outbound calls from Bubble to Framer (reading and writing CMS items), the Bubble Free plan is sufficient — the API Connector plugin works on all plans. You only need a paid Bubble plan (Starter or above) if you want to receive inbound Framer webhook events via a Bubble Backend Workflow.
Can I embed my Framer site inside a Bubble page?
Strongly not recommended. Framer's CSS animations, responsive layouts, and smart components are built for full-page rendering and break inside iframes. You cannot share authentication state between a Framer iframe and a Bubble page. Keep Framer and Bubble on separate domains — Framer for your public marketing site, Bubble for your authenticated app.
How do I find my Framer CMS Collection ID?
There are two ways: (1) In the Framer editor, open the CMS panel, click your collection, and look at the browser URL — it contains the collection ID after /cms/. (2) Make a GET request to https://api.framer.com/store/api/v1/collections using your API token — the response lists all collections with their IDs and names.
What happens if I update a Framer CMS item from Bubble while a Framer editor is also editing it?
The last write wins. If a Framer editor is actively editing a CMS item and your Bubble Workflow PATCHes the same item simultaneously, one of the writes will overwrite the other. To avoid conflicts, consider implementing a locking mechanism in Bubble (a 'locked_by' field on the data type) that prevents API updates while a Framer editor session is active.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation