# Figma

- Tool: Bubble
- Difficulty: Intermediate
- Time required: 1–3 hours
- Last updated: July 2026

## TL;DR

Bubble has no native Figma import — no plugin converts Figma frames into Bubble elements. The integration has two angles: (1) design handoff using Figma's Dev Mode to extract exact color hex codes, spacing, and typography for manual recreation in Bubble's Design tab; (2) Figma REST API via Bubble's API Connector using the custom `X-Figma-Token` header to read file data, export assets, or sync design tokens from a Figma file into a Bubble admin dashboard.

## Figma + Bubble: Design Handoff and API Integration

When people search 'Bubble Figma integration', they expect to find a plugin that converts Figma frames directly into Bubble elements — a Figma-to-Bubble importer. That plugin doesn't exist. Bubble's visual editor is proprietary and doesn't support design imports. Understanding this upfront saves hours of searching.

What does exist is a two-part workflow that covers most real use cases:

First, Figma as a design reference. When your designer hands off a Figma file, Figma's Dev Mode (press F in Figma, or access it via the Figma menu) transforms every element into inspectable CSS values. Click on a button in Figma Dev Mode and you'll see the exact hex color, pixel padding, border radius, font size, and font weight — all the values you need to recreate it faithfully in Bubble's Design tab. This design handoff workflow has no API calls and works on any Figma plan.

Second, Figma REST API via Bubble's API Connector. This is genuine integration: Bubble calls the Figma API at `https://api.figma.com/v1` to read file structure, export frame thumbnails as images, or sync design token values (colors, spacing) from a Figma Variables file into a Bubble database. The result is a Bubble admin tool where non-technical team members can view Figma component lists, download asset exports, or see the current design token values — all without opening Figma.

A critical gotcha for the API path: Figma uses the non-standard header `X-Figma-Token` rather than the typical `Authorization: Bearer` format. In Bubble's API Connector, this means adding a custom shared header named `X-Figma-Token` (not using the built-in Authorization header field). Getting this wrong causes 403 errors that look like authentication failures.

## Before you start

- A Figma account — any plan includes API access (free tier supports 3 Figma files)
- A Figma Personal Access Token (generated in Figma → Account Settings → Personal access tokens)
- A Bubble app with the API Connector plugin installed (Plugins tab → Add plugins → 'API Connector' by Bubble)
- For Backend Workflow use cases (automated syncing): a paid Bubble plan (Starter or above)
- The File Key of your Figma file — found in the URL: `figma.com/file/{FILE_KEY}/...`

## Step-by-step guide

### 1. Use Figma Dev Mode for Design Handoff (No API Required)

Before connecting Bubble to the Figma API, understand the design handoff workflow — it's the fastest path and covers the most common use case. Open your Figma file and press F to enter Dev Mode (or click the '</>' icon in the top-right toolbar). If you're using Figma's free plan, Dev Mode may require a paid seat — check your plan's feature access.

In Dev Mode, click on any element in the Figma canvas. The right-hand inspect panel displays all CSS properties: fill color as a hex code, padding values in pixels, border radius, font family, font weight, font size, and line height.

Here's how to translate each value into Bubble's editor:
- **Colors**: In Bubble, click on any element → Style tab → Background color or Border color → paste the hex code from Figma's fill color property.
- **Typography**: Bubble's Styles tab (Styles panel in the editor) → create a reusable text style → enter the font family, size, and weight from Figma's typography panel. Set line-height in the element's advanced style settings.
- **Spacing**: In Bubble, select an element → Layout tab → set margin and padding values from Figma's spacing values.
- **Border radius**: In Bubble, element Properties → Border radius → enter the pixel value from Figma.

For complex layouts, use Figma's alignment guides and the spacing numbers to set Bubble element positions and widths. Bubble's layout engine (Columns and Rows) doesn't map 1:1 to Figma's auto-layout, but the visual values from Dev Mode give you the exact numbers to aim for.

```
// Figma Dev Mode value extraction cheatsheet
// (Values shown in Figma's right-hand inspect panel when in Dev Mode)

// Colors → Bubble: Background color field (hex code)
// Example: Fill #1E40AF → Bubble hex input #1E40AF

// Typography → Bubble: Styles panel → Text style
// Example: Inter 16px 600 weight → Font: Inter, Size: 16, Weight: Semi-bold

// Spacing → Bubble: Layout tab (margin/padding)
// Example: Padding 16px top/bottom 24px left/right → Margin: 16 top, 24 left

// Border radius → Bubble: Property panel → Border radius
// Example: Corner radius 8px → Border radius: 8

// Shadow → Bubble: Style → Box shadow
// Figma: box-shadow: 0 4px 6px rgba(0,0,0,0.1)
// Bubble: X 0, Y 4, Blur 6, Color #000000 at 10% opacity
```

**Expected result:** Your Bubble elements match the Figma designs with accurate colors, typography, spacing, and border radii. The visual output in Bubble's preview closely matches the Figma frames without requiring any API integration.

### 2. Generate a Figma Personal Access Token

To call the Figma REST API from Bubble, you need a Personal Access Token (PAT). This token authenticates your Bubble API Connector as if it were you — it has access to all Figma files in your account.

In Figma, click your profile avatar in the top-left corner of the Figma home screen. Click 'Settings' in the dropdown menu. Scroll down to the 'Personal access tokens' section. Click 'Generate new token'. Give it a descriptive name like 'Bubble API Connector' and select the permissions scope — for read-only access to files (sufficient for most use cases), leave the default read permissions. Click 'Generate token'.

Copy the token immediately — Figma only shows it once. If you lose it, you'll need to delete and regenerate. The token looks like a long string starting with `figd_...` (newer tokens) or a mix of alphanumeric characters (older format).

Note your Figma File Key as well. Open the Figma file you want to access, look at the browser URL: `https://www.figma.com/file/ABC123XYZ/My-Design-File`. The `ABC123XYZ` portion is the File Key you'll use in API calls.

Treat the Figma token like a password — anyone with this token can read all your Figma files. In Bubble's API Connector, always mark the header value as 'Private' so it's encrypted server-side.

```
// Figma Personal Access Token location:
// Figma Home → Profile avatar (top-left) → Settings
// → Scroll to 'Personal access tokens' → Generate new token

// Token format (newer API):
// figd_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890

// File Key location (in browser URL):
// https://www.figma.com/file/{FILE_KEY}/My-Design-File
//                             ↑
//                        Copy this value
//
// Example: https://www.figma.com/file/AbC123XYZ456/Brand-Design-System
// File Key: AbC123XYZ456
```

**Expected result:** A Figma Personal Access Token has been generated and copied. The Figma File Key for the design file you want to access is noted. Both values are stored securely (e.g., in a password manager) before proceeding.

### 3. Configure the Figma API in Bubble's API Connector

Now set up Bubble's API Connector to authenticate with the Figma API. This step has one critical gotcha: Figma uses the custom header `X-Figma-Token`, NOT the standard `Authorization: Bearer` format. If you enter the token in Bubble's built-in 'Authorization' field, you'll get 403 errors.

In the Bubble editor, click Plugins in the left sidebar. If you don't see the API Connector, click 'Add plugins', search for 'API Connector', and install it (it's the official plugin by Bubble, free). Click on API Connector.

Click 'Add another API'. Name it 'Figma API'. In the 'Root URL' field, enter `https://api.figma.com/v1`. Do NOT click the 'Authentication' dropdown — Figma doesn't use a standard Bearer token auth; it uses a custom header.

Instead, scroll down to 'Shared headers'. Click 'Add a shared header'. In the 'Key' field, type exactly: `X-Figma-Token`. In the 'Value' field, paste your Figma Personal Access Token. Click the 'Private' checkbox — this is essential to keep the token server-side and out of the browser.

Do not add a second Authorization header. With just the `X-Figma-Token` custom header configured, all calls in this API group will authenticate automatically.

```
// Bubble API Connector configuration for Figma
// (Conceptual — configured visually in Bubble editor)
{
  "api_name": "Figma API",
  "root_url": "https://api.figma.com/v1",
  "shared_headers": [
    {
      "key": "X-Figma-Token",
      "value": "figd_YOUR_PERSONAL_ACCESS_TOKEN",
      "private": true
    }
  ]
}

// CRITICAL: Figma does NOT use "Authorization: Bearer"
// Wrong (causes 403 error):
// Authorization: Bearer figd_your_token

// Correct:
// X-Figma-Token: figd_your_token
```

**Expected result:** The Figma API appears in Bubble's API Connector with the root URL `https://api.figma.com/v1` and one shared header `X-Figma-Token` marked as Private (shown with a lock icon). No Authorization header is configured.

### 4. Add an Initialize Call to Verify Authentication

Before building more complex Figma API calls, verify your token is working with a simple 'get me' endpoint that returns information about the authenticated Figma user. This call also initializes the API in Bubble's system.

In the Figma API you created, click 'Add a call'. Name it 'Get Current User'. Set the method to GET. In the path field, enter `/me`. Leave the body empty.

Click 'Initialize call'. Bubble sends a real request to `https://api.figma.com/v1/me` with your `X-Figma-Token` header. If authentication is working, you'll see a response with your Figma user data: `id`, `email`, `handle` (username), and `img_url`.

Set 'Use as' to 'Data' (this call returns a single object, not an action). Bubble auto-detects the field types from the response. Click 'Save'.

If the Initialize call returns a 403 Forbidden error, the most common cause is entering the token in the wrong header. Double-check: the key must be `X-Figma-Token` (capital X, capital F, capital T) with the exact casing Figma expects. The value should be only the token string, no quotes, no 'Bearer' prefix.

```
// Figma API: Get Current User
// Method: GET
// Path: /me
// Headers (from shared config): X-Figma-Token: [private]

// Expected successful response:
{
  "id": "123456789",
  "email": "designer@company.com",
  "handle": "designer_name",
  "img_url": "https://s3-alpha.figma.com/profile/..."
}

// 403 Forbidden response (wrong header):
{
  "status": 403,
  "err": "Forbidden"
}

// 401 Unauthorized (missing or invalid token):
{
  "status": 401,
  "err": "Unauthorized"
}
```

**Expected result:** Bubble's API Connector shows the 'Get Current User' call as 'Initialized' with auto-detected fields including `id`, `email`, `handle`, and `img_url`. The call is available in Bubble's workflow editor under Plugins → Figma API → Get Current User.

### 5. Create Calls to Read Figma File Data and Export Assets

With authentication working, build the core Figma API calls for your use case. The two most useful calls for Bubble integrations are: reading file structure (to display pages and frames) and exporting component images (to get thumbnail URLs).

For reading file structure, add a new call: name it 'Get File', method GET, path `/files/{fileKey}`. In the call parameters, add a path parameter `fileKey` (the File Key you noted earlier) — mark it as a literal value or let users provide it. Add the query parameter `depth=1` to limit the response depth; without this parameter, large Figma files return the complete document tree and can exceed Bubble's 5MB API response limit.

For exporting images, add another call: name it 'Export Frame Images', method GET, path `/images/{fileKey}`. Add query parameters: `ids` (the node IDs of frames to export, comma-separated) and `format` (set to `svg`, `png`, or `jpg`). The response contains a `images` object mapping node IDs to signed S3 URLs for the exported images.

Important: Figma's export image URLs are pre-signed S3 URLs that expire in approximately 14 days. Never store these URLs permanently in your Bubble database — always re-fetch them on demand. Store only the node IDs and generate fresh export URLs when needed.

RapidDev's team builds custom design-ops tools in Bubble that connect to Figma's API for asset management — if you're building a complex integration, a free scoping call at rapidevelopers.com/contact can help you architect the right approach.

```
// Call 1: Get File Structure
// Method: GET
// Path: /files/{fileKey}?depth=1
// Parameters:
//   fileKey: AbC123XYZ456 (your Figma File Key)
//   depth: 1 (limits response depth to avoid 5MB limit)

// Sample response structure (depth=1):
{
  "name": "Brand Design System",
  "role": "viewer",
  "lastModified": "2026-07-10T12:00:00Z",
  "document": {
    "id": "0:0",
    "name": "Document",
    "type": "DOCUMENT",
    "children": [
      { "id": "1:0", "name": "Page 1", "type": "CANVAS" },
      { "id": "2:0", "name": "Components", "type": "CANVAS" }
    ]
  }
}

// Call 2: Export Frame Images
// Method: GET
// Path: /images/{fileKey}?ids={nodeIds}&format=png&scale=2
// Parameters:
//   fileKey: AbC123XYZ456
//   ids: 1:23,1:45  (comma-separated node IDs)
//   format: png
//   scale: 2 (2x for retina)

// Sample response:
{
  "err": null,
  "images": {
    "1:23": "https://figma-alpha-api.s3.us-west-2.amazonaws.com/runs/...",
    "1:45": "https://figma-alpha-api.s3.us-west-2.amazonaws.com/runs/..."
  }
}
// WARNING: These S3 URLs expire in ~14 days — never store permanently
```

**Expected result:** The 'Get File' call initializes successfully and Bubble auto-detects the document structure fields (name, lastModified, document.children). The 'Export Frame Images' call initializes with the `images` object containing at least one signed URL. Both calls appear in the workflow editor under Plugins → Figma API.

### 6. Build a Bubble UI to Display Figma File Data

With the Figma API calls configured, build a Bubble page that displays file structure and component thumbnails. This step creates a practical admin tool that team members can use to browse Figma assets without needing a Figma account.

In Bubble's page editor, add a Repeating Group to display Figma file pages. In the Repeating Group's data source, set it to 'Get data from an external API' → select your 'Get File' call. The Repeating Group populates with the pages (CANVAS nodes) from your Figma file.

For each row in the Repeating Group, add a Text element bound to `Current cell's document children name` to show the page name. Add a second level Repeating Group inside the first to show frames within each page (requires a second API call to `/files/{fileKey}?ids={pageId}` for each page's children).

For component thumbnails, use a workflow triggered by a button click: 'When button is clicked → Plugins → Figma API → Export Frame Images → set State → show image from dynamic URL'. The Image element's URL is set to the state variable containing the signed S3 URL.

For the design token sync use case (optional): create a Bubble data type called 'Design Token' with fields `token_name` (text), `token_value` (text), and `token_type` (text). Create a Backend Workflow that calls the Figma Variables API (`GET /files/{fileKey}/variables/local`) and loops through the response to create or update Design Token records. Schedule this workflow to run daily via Bubble's Recurring Events (requires a paid plan).

```
// Bubble Workflow: Sync Figma Design Tokens to Bubble Database
// (Backend Workflow, requires paid Bubble plan)
//
// Trigger: API call or scheduled recurring event
//
// Step 1: Call 'Get Variables' (Figma Variables API)
// Method: GET
// Path: /files/{fileKey}/variables/local
//
// Sample response:
{
  "status": 200,
  "meta": {
    "variables": {
      "VariableID:1": {
        "id": "VariableID:1",
        "name": "color/primary",
        "resolvedType": "COLOR",
        "valuesByMode": {
          "1:0": { "r": 0.118, "g": 0.251, "b": 0.686, "a": 1 }
        }
      },
      "VariableID:2": {
        "id": "VariableID:2",
        "name": "spacing/base",
        "resolvedType": "FLOAT",
        "valuesByMode": {
          "1:0": 8
        }
      }
    }
  }
}

// Step 2: Bubble workflow - Create or update 'Design Token' thing
// For each variable in response:
//   - Search for Design Token where token_name = variable.name
//   - If found: update token_value and token_type
//   - If not found: create new Design Token with name, value, type
```

**Expected result:** A Bubble page displays a list of Figma file pages from the API response in a Repeating Group. Clicking a 'Export' button triggers the Figma image export call and displays the component thumbnail. For token sync, the Design Token data type in Bubble is populated with color and spacing values from the Figma Variables response.

## Best practices

- Always use the `X-Figma-Token` custom header in Bubble's API Connector — never the `Authorization: Bearer` format. Figma's non-standard auth scheme is the single biggest source of 403 errors in Bubble + Figma integrations. Mark the header as 'Private' so the token stays server-side.
- Add the `?depth=1` parameter to all `/files/{fileKey}` calls to prevent large design system files from hitting Bubble's 5MB API response limit. If you need deeper content, fetch specific nodes by ID using the `?ids=` parameter rather than the full document tree.
- Never store Figma image export URLs (from `/images/{fileKey}`) in Bubble's database. These are pre-signed S3 URLs that expire in approximately 14 days. Generate fresh export URLs on demand using Bubble workflows, or re-upload the images to permanent storage during the initial fetch.
- For design handoff, always use Figma's Dev Mode (press F in the Figma editor) rather than eyeballing the visual canvas. Dev Mode shows exact pixel values, hex codes, and CSS properties — the visual canvas can be misleading due to zoom level and display scaling.
- When building a Figma Variables sync workflow in Bubble, convert Figma's RGBA color format (values 0–1 range) to hex before storing in Bubble. Figma returns color values as `{r: 0.118, g: 0.251, b: 0.686, a: 1}` — multiply each by 255 and convert to hex for Bubble's color fields. Use a Bubble 'Run JavaScript' action with the Toolbox plugin for this conversion.
- Create a Privacy Rule in Bubble for any data type that stores Figma design data (e.g., 'Design Token'). Without a Privacy Rule, the data type is publicly accessible via Bubble's API. Set a rule that restricts access to authenticated admin users only.
- If you're building a multi-tenant Bubble app where different teams have their own Figma workspaces, do not use a single hardcoded Figma token. Instead, build an OAuth 2.0 flow using a Bubble Backend Workflow to exchange user authorization codes for per-user Figma tokens — this requires a paid Bubble plan and a registered Figma OAuth application.

## Use cases

### Design Handoff: Recreate Figma Screens in Bubble with Pixel-Level Accuracy

Your designer delivers a Figma file with app screens — dashboards, forms, landing pages. Use Figma's Dev Mode to extract exact design values (colors, typography, spacing, border radii) and manually recreate each element in Bubble's Design tab, achieving a faithful implementation without a Figma importer plugin.

Prompt example:

```
My designer sent me a Figma file with the UI for my Bubble app. How do I use Figma to extract the exact colors, fonts, and spacing to recreate the design in Bubble's editor?
```

### Build a Bubble Admin Tool That Reads Figma File Structure

Create a Bubble internal tool where team members can view the structure of a Figma design file — listing pages, frames, and components — without needing Figma access. The Bubble app calls the Figma REST API to fetch the file document tree and displays it in a searchable, sortable Repeating Group.

Prompt example:

```
I want to build an internal tool in Bubble where my team can browse our Figma design system file structure and export specific frame thumbnails as images. How do I connect Bubble to the Figma API?
```

### Sync Figma Design Tokens to a Bubble Style Guide Dashboard

Use the Figma Variables API to read your design system's color tokens, spacing values, and typography settings. A Bubble Backend Workflow syncs these token values into a Bubble data type called 'Design Token'. The result is a living style guide dashboard in Bubble that non-designers can reference when building new features.

Prompt example:

```
We have a Figma design system with color and spacing tokens. Can I use Bubble to sync those token values automatically and display them in a Bubble-based style guide that our developers can reference?
```

## Troubleshooting

### Figma API returns 403 Forbidden when called from Bubble's API Connector

Cause: The most common cause is using `Authorization: Bearer your_token` instead of the custom `X-Figma-Token: your_token` header. Figma's API uses a non-standard authentication scheme — entering the token in Bubble's built-in Authorization header field causes 403 errors even with a valid token.

Solution: In Bubble's API Connector, remove any Authorization header you may have added. Instead, go to Shared Headers and add a custom header with Key = `X-Figma-Token` (exact casing) and Value = your token, with the 'Private' checkbox enabled. Delete the old Authorization header if one exists, then re-initialize the call. The 403 error disappears once the correct header name is used.

```
// Remove this:
// Key: Authorization
// Value: Bearer figd_your_token

// Replace with:
// Key: X-Figma-Token
// Value: figd_your_token
// Private: checked
```

### Bubble's API Connector shows 'There was an issue setting up your call' when initializing the Figma file endpoint

Cause: Either the Figma file is too large (responses exceeding Bubble's 5MB limit cause initialization failures), or the File Key in the URL is incorrect, or the file returns an empty children array because it has no published content.

Solution: Add the `?depth=1` query parameter to the `/files/{fileKey}` call to limit response size. Verify the File Key by copying it directly from the Figma file's browser URL. Ensure the Figma file has at least one page with content. For very large design systems, use `?ids=nodeId1,nodeId2` to request only specific nodes rather than the full document tree.

```
// Instead of:
// GET /files/{fileKey}

// Use:
// GET /files/{fileKey}?depth=1
// OR for specific nodes:
// GET /files/{fileKey}?ids=1:23,2:45
```

### Figma export image URLs stored in Bubble stop working after a few days

Cause: Figma's image export URLs from `/images/{fileKey}` are pre-signed AWS S3 URLs with an expiration of approximately 14 days. Storing them permanently in Bubble's database causes broken images once they expire.

Solution: Do not store Figma export URLs in Bubble's database fields. Instead, use Bubble's custom states to hold the URL temporarily during a user session, or re-call the Figma export endpoint each time the image is needed. If you need permanent asset URLs, download the image using the temporary URL and upload it to Bubble's File Manager or an external storage service like AWS S3 or Cloudflare R2.

### Figma API works in Postman but fails with 'There was an issue setting up your call' in Bubble

Cause: Bubble's API Connector makes server-side requests from Bubble's cloud infrastructure, not from your browser. If the Figma file is private and IP-restricted, or if the response structure varies between testing in Postman (logged-in context) and Bubble's server call (token-only context), the responses may differ.

Solution: Confirm the Figma Personal Access Token has access to the specific file — the token inherits your account's file access. If the file is in a team workspace, ensure your account has at least Viewer access to that workspace. Test the exact endpoint URL and headers in Postman with only the `X-Figma-Token` header (remove any session cookies) to simulate the server-side call context.

## Frequently asked questions

### Is there a Figma plugin that imports Figma designs directly into Bubble?

No. As of 2026, there is no official or widely-used plugin that converts Figma frames into Bubble elements. Bubble's visual editor uses a proprietary element system that doesn't map directly to Figma's layer/component structure. The recommended approach is design handoff: use Figma's Dev Mode to extract exact CSS values and manually recreate the design in Bubble's editor.

### Why do I keep getting 403 errors when calling the Figma API from Bubble?

The most common cause is using the wrong header name. Figma uses `X-Figma-Token: your_token` — NOT `Authorization: Bearer your_token`. In Bubble's API Connector, add a custom shared header with the exact key `X-Figma-Token` (case-sensitive) and the Private checkbox enabled. Do not use Bubble's built-in Authorization header field for Figma authentication.

### Does Figma API access require a paid Figma plan?

No. Figma API access is included on all plans, including the free tier. The free plan limits you to 3 Figma files and 3 FigJam files, but those files are accessible via the API. Figma's Dev Mode, however, may require a paid Figma plan (Starter or above) for team members who aren't the file owner — check your specific plan's Dev Mode access.

### Can Bubble automatically update Figma content when someone changes data in Bubble?

Not directly. Bubble can call the Figma REST API to read data, but Figma doesn't have a write API for updating design file content from external tools. The Figma CMS API (for Framer) exists, but Figma's own design files are read-only via the REST API. If you need to sync data bidirectionally between a visual tool and Bubble, Framer's CMS API supports write operations — see the Framer integration for that workflow.

### How do I get the Node IDs for specific Figma frames to export as images?

In Figma Dev Mode, right-click on any frame and select 'Copy link'. The URL contains `node-id=1-23` (for example). Replace the hyphen with a colon to get the API node ID format: `1:23`. Alternatively, call `GET /files/{fileKey}?depth=2` and look at the `children` array in the response — each object has an `id` field that serves as the node ID for image export calls.

### What happens to stored Figma image export URLs after 14 days?

They expire and return 403 Access Denied errors when loaded in a browser or image element. Figma's export image URLs are pre-signed AWS S3 URLs with a built-in expiration. Never store these URLs in Bubble's database as permanent references. Either generate fresh export URLs each time the image is displayed, or download the image immediately after exporting and re-upload it to Bubble's File Manager or an external storage service.

---

Source: https://www.rapidevelopers.com/bubble-integrations/figma
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/figma
