# Confluence

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

## TL;DR

Connect Bubble to Confluence Cloud using the API Connector plugin with Basic Auth (Atlassian email + API token). The base URL must include /wiki/rest/api — missing the /wiki prefix causes 404 on every request. Use CQL (Confluence Query Language) to power smart search and embed a searchable knowledge base in a Bubble app. No Bubble marketplace plugin exists for Confluence.

## Embed a searchable Confluence knowledge base in your Bubble app

Confluence is where teams write documentation — setup guides, process specs, onboarding checklists, architecture decisions. But external users (clients, support agents, new hires) often don't have Confluence accounts. Connecting Confluence to a Bubble app lets you expose the right documentation to the right audience inside a custom portal, without giving everyone a Confluence login.

The most valuable Bubble use case for Confluence is a searchable knowledge base: a Bubble page where support agents or customers type a question and the app returns matching Confluence pages using CQL — Confluence's query language. CQL supports full-text search (`text~'query'`), space filtering, and content type filtering, making it far more precise than a simple keyword search.

Two critical details that trip up most Bubble developers:

First, the base URL. Confluence Cloud and Jira both live on `your-domain.atlassian.net`, but they have different API paths. Jira uses `/rest/api`. Confluence uses `/wiki/rest/api`. Omitting `/wiki` returns 404 on every Confluence call — even though the domain is correct.

Second, authentication. Confluence Cloud does not accept your Atlassian account password via the API. You must generate an API token from Atlassian's identity portal and use that as the password in Basic Auth. Bubble's API Connector handles the Base64 encoding automatically when you select the Basic Auth type.

## Before you start

- A Confluence Cloud account (Free plan works for API access, with up to 10 users and 2 GB storage; Standard from $5.75/user/mo for larger teams)
- Your Atlassian Cloud subdomain (e.g., if your Confluence URL is acme.atlassian.net, your subdomain is 'acme')
- An Atlassian API token — generated separately from your account password at id.atlassian.com
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → search 'API Connector' by Bubble)
- Basic familiarity with Bubble's workflow editor, repeating groups, and HTML elements

## Step-by-step guide

### 1. Generate an Atlassian API token

Log into Atlassian's identity management portal at `id.atlassian.com`. Click your profile avatar in the top-right corner, then select 'Manage account'. In the left sidebar, click 'Security'. Scroll down to the 'API token' section and click 'Create and manage API tokens'. Click 'Create API token', give it a descriptive label like 'Bubble Integration', and click 'Create'.

Copy the token immediately — Atlassian only shows it once. If you close the dialog without copying, you will need to delete the token and create a new one.

IMPORTANT: This token is different from your Atlassian account password. Using your account password instead of an API token in the Basic Auth configuration causes 401 errors on all Confluence API requests. Confluence Cloud specifically requires API tokens for programmatic access.

Note your Atlassian account email address as well — you will need both the email and the API token for the Basic Auth configuration in Bubble.

**Expected result:** You have an Atlassian API token (a long alphanumeric string) and your Atlassian account email address ready for the Bubble setup.

### 2. Configure the Confluence API Connector with correct base URL and Basic Auth

In your Bubble app, open the Plugins tab and confirm the API Connector plugin is installed. Click 'Add another API' and name it 'Confluence'.

SET THE AUTHENTICATION TYPE TO 'Basic Auth'. In the Username field, enter your Atlassian account email address. In the Password field, enter the API token you just generated. Tick 'Private' for the password field — Bubble will Base64-encode the email:token pair automatically.

Set the base URL to: `https://YOUR_SUBDOMAIN.atlassian.net/wiki/rest/api`

Replace YOUR_SUBDOMAIN with your Atlassian Cloud subdomain (e.g., if your Confluence is at acme.atlassian.net, use `https://acme.atlassian.net/wiki/rest/api`).

CRITICAL: The `/wiki/rest/api` path segment is mandatory. Jira uses `/rest/api` on the same domain, but Confluence is served under `/wiki`. Every single Confluence API call will return 404 if you omit `/wiki` from the base URL. This is the number one setup mistake for this integration.

Add a shared header: Content-Type: application/json.

```
{
  "api_name": "Confluence",
  "base_url": "https://YOUR_SUBDOMAIN.atlassian.net/wiki/rest/api",
  "auth_type": "Basic Auth",
  "username": "your-email@example.com",
  "password": "<private API token>",
  "headers": [
    {
      "key": "Content-Type",
      "value": "application/json",
      "private": false
    }
  ]
}
```

**Expected result:** The Confluence API group appears in your API Connector list with Basic Auth configured. The password field shows a lock icon indicating it is Private.

### 3. Add and initialize the content search call

Inside the Confluence API group, click 'Add another call'. Name it 'Search Pages'. Set the method to GET and the path to `/content/search`.

Add query parameters by clicking 'Add parameter':
- cql (text, dynamic — this is your CQL query string)
- limit (number, default 25)
- expand (text, default: space,version)
- start (number, default 0, for pagination)

Before initializing, you need to understand CQL (Confluence Query Language). CQL is a structured query language specific to Confluence. Key operators:
- `type = 'page'` — search only pages (not blog posts or attachments)
- `text ~ 'keyword'` — full-text search containing 'keyword'
- `space.key = 'ENG'` — filter to a specific space
- `AND` — combine conditions

For initialization, enter a real CQL query as the default cql value: `type='page' AND space.key='YOUR_SPACE_KEY'` (replace YOUR_SPACE_KEY with an actual space key from your Confluence). Click 'Initialize call'. Bubble sends the real request and detects response fields including results (array with id, title, type, status), _links, size, and start.

Set 'Use as' to 'Data' and tick 'List'. Note the nested structure: results is the array of pages, and each result has a _links.webui field containing the Confluence page URL.

```
GET https://YOUR_SUBDOMAIN.atlassian.net/wiki/rest/api/content/search
  ?cql=type%3D'page'%20AND%20text~'<searchTerm>'
  &limit=25
  &expand=space,version
Authorization: Basic <base64-encoded-email:token>
```

**Expected result:** The 'Search Pages' call is initialized and shows detected fields: results list containing id, title, type, and _links objects. Bubble generates a 'Confluence Search Pages' data type with these fields.

### 4. Fetch full page content with body expansion

Confluence's search endpoint returns page metadata (title, ID, links) but not the actual page body content. To display content, you need a separate call to the content endpoint with the body expanded.

Add another call: 'Get Page Content'. Method: GET. Path: `/content/{pageId}`. Add a dynamic path parameter pageId (text). Add a query parameter: expand (text, default: body.view).

The `body.view` expand returns the page content as rendered HTML. This is important — Confluence does not return plain text. The content appears in the `body.view.value` field as a string of HTML markup.

Initialize the call using a real page ID from your Confluence. Click on any page in Confluence and look at the URL: the number after `/pages/` is the page ID. Use this for initialization.

In your Bubble app, when a user clicks a search result in the repeating group, trigger a workflow: call 'Get Page Content' with the selected result's ID. Store the body.view.value field in a Bubble custom state (type: text).

To display the HTML content in Bubble, add an HTML element to your page (from the Elements panel, search 'HTML' — it is listed as 'HTML' element type). Set its content to the custom state containing the page body. The HTML element renders formatted HTML properly — headings, bold text, tables, and lists all display correctly. A standard Bubble text element would show raw HTML tags.

```
GET https://YOUR_SUBDOMAIN.atlassian.net/wiki/rest/api/content/{pageId}?expand=body.view
Authorization: Basic <base64-encoded-email:token>

// Response structure (relevant fields):
// {
//   "id": "12345",
//   "title": "Page Title",
//   "body": {
//     "view": {
//       "value": "<p>HTML content here</p>",
//       "representation": "view"
//     }
//   },
//   "_links": {
//     "webui": "/spaces/ENG/pages/12345/Page+Title"
//   }
// }
```

**Expected result:** Clicking a search result triggers the 'Get Page Content' call and stores the HTML body in a custom state. The HTML element on your page renders the full Confluence page content including formatted text, headings, and code blocks.

### 5. Build the search interface with space filter and repeating group

First, add a call to fetch available Confluence spaces so users can filter results. Add call 'Get Spaces': GET `/space`, with query params limit (25), type (global). Initialize this call — it returns a results array of spaces with key, name, and type fields.

On your Bubble page, add:
1. A Dropdown element for space selection. Set choices to 'Get data from an external API → Confluence - Get Spaces'. Display field: current option's name. Value field: current option's key.
2. A Text Input element for the search term.
3. A Search button (or set the workflow to trigger on input change with a 500ms debounce via Bubble's 'run only when' condition).
4. A Repeating Group for results.

The repeating group data source: 'Get data from an external API → Confluence - Search Pages'. Pass the CQL parameter as a dynamic value:

`type='page' AND text~'` + Search Input's value + `' AND space.key='` + Space Dropdown's value + `'`

If the dropdown has 'All Spaces' as a default, use a Bubble conditional to remove the space filter from the CQL when 'All Spaces' is selected.

Inside the repeating group cell, add:
- Text: current cell's result's title (make it bold)
- Text: current cell's result's space's name
- Text: current cell's result's version's by's displayName (author name)
- A button: 'Open in Confluence' linking to the Atlassian base URL + current cell's result's _links's webui field
- A button: 'Preview' that triggers the Get Page Content workflow

RapidDev's team has built internal knowledge portals for multiple Bubble clients using exactly this Confluence integration pattern — if you need a multi-space portal with access controls, book a free scoping call at rapidevelopers.com/contact.

```
// CQL query construction for Bubble dynamic expression:
// type='page' AND text~'{searchInput.value}' AND space.key='{spaceDropdown.value}'

// With no space filter (All Spaces selected):
// type='page' AND text~'{searchInput.value}'

// With parent page constraint:
// type='page' AND ancestor='{parentPageId}' AND text~'{searchInput.value}'
```

**Expected result:** The page shows a space dropdown and search input. Typing a search term and selecting a space runs the Confluence CQL search and displays matching page titles, spaces, and authors. Clicking 'Preview' opens the page content in an HTML element modal.

### 6. Add pagination and handle the 10-user free plan limit

Confluence returns paginated results using `start` (offset) and `limit` query parameters. Each response includes a `_links.next` field if more pages exist. For Bubble, implement pagination using a 'Load more' button pattern.

Add a number custom state to your page: name it 'current_page_start', default 0. When the user clicks 'Load more', run a workflow:
1. Add step: Set state 'current_page_start' = current_page_start + 25 (your page size)
2. The repeating group re-fetches with the updated start value

For the Confluence Free plan (10 users, 2 GB storage): API access works fully on the free plan. The 10-user limit refers to Confluence editors and viewers, not to API requests. A Bubble app reading Confluence via API counts as a single API connection, not as 10 individual users accessing Confluence.

One practical limitation: if your Confluence space has pages created by more than 10 users (impossible on the free plan), you may see author information in API responses that references accounts you cannot administer. This is not an issue for the reading/searching use case described here.

For client projects, note that a Confluence Cloud Standard plan ($5.75/user/month) may be required if the client already has more than 10 Confluence users. The API integration itself works the same regardless of plan.

```
// Pagination pattern for Confluence content search
GET /wiki/rest/api/content/search
  ?cql=type='page' AND text~'query'
  &limit=25
  &start=<current_page_start_state>

// Response includes:
// {
//   "results": [...],
//   "start": 0,
//   "limit": 25,
//   "size": 25,
//   "_links": {
//     "next": "/rest/api/content/search?...&start=25"
//   }
// }
// If _links.next is empty, you are on the last page
```

**Expected result:** The search interface handles multi-page results with a 'Load more' button that increments the start offset and appends new results to the existing repeating group display.

## Best practices

- Always include /wiki/rest/api in the Confluence API base URL — this is Confluence-specific and different from Jira's path structure on the same Atlassian domain.
- Use Atlassian API tokens, never your account password. Store the token as Private in Bubble API Connector's Basic Auth password field.
- Test CQL queries in Confluence's Advanced Search before wiring them into Bubble. This saves significant debugging time and confirms the query logic before integration.
- Display Confluence page body content in a Bubble HTML element, not a standard text element. The body.view.value field returns HTML markup that only renders correctly in an HTML element.
- Add Privacy Rules (Data tab → Privacy) if you store any Confluence data in Bubble's database — restrict access to authenticated users with appropriate roles.
- Implement a minimum character count condition on search triggers (e.g., only search when the input has more than 2 characters) to avoid running unnecessary API calls and wasting Workload Units.
- Cache frequently accessed Confluence spaces and popular page content in Bubble's database rather than calling the Confluence API on every page load. Use a scheduled backend workflow to refresh the cache periodically.
- If you connect Confluence and Jira in the same Bubble app, keep them as separate API Connector groups — they share auth credentials but have different base URLs and response structures.

## Use cases

### Searchable internal knowledge base portal

Build a Bubble page where support agents or employees type a search term and the app returns matching Confluence pages using CQL full-text search. Results show the page title, space name, and an excerpt. Clicking a result opens the full page content in a Bubble HTML element inside a modal — no Confluence account needed.

Prompt example:

```
Create a Bubble page with a text input for search. On input change (with 500ms debounce), call GET https://your-domain.atlassian.net/wiki/rest/api/content/search with CQL parameter: type='page' AND text~'{searchInput}' AND space.key='ENG'. Display results in a repeating group showing title, space name, and last updated date. On row click, fetch the page body and display in an HTML element inside a popup.
```

### Client onboarding portal with filtered documentation

Build a Bubble client portal where each client sees only the Confluence pages tagged with their project space. Use a space dropdown to filter CQL queries to the relevant Confluence space. Clients read documentation and implementation guides without needing Confluence access, and you control which spaces are visible per client using Bubble's data conditions.

Prompt example:

```
Create a Bubble page with a space-key dropdown (values populated from GET /space endpoint). When space changes, call GET /content/search with CQL type='page' AND space.key='{selectedSpace}' AND ancestor='{parentPageId}'. Show results in a hierarchical repeating group. Add a Bubble conditional to show/hide spaces based on the current user's assigned client record.
```

### Confluence page creator from a Bubble form

Let team members create new Confluence documentation pages directly from a Bubble form without opening Confluence. A Bubble form collects page title, parent page ID (from a dropdown), and body content. On submit, a POST /content call creates the page in the selected Confluence space and returns the URL.

Prompt example:

```
Create a Bubble form page with title input, space dropdown (GET /space), parent page dropdown (GET /content filtered by space and type=page), and a multi-line text area for body content. On submit, call POST https://your-domain.atlassian.net/wiki/rest/api/content with JSON body containing title, type, space.key, ancestors, and body.storage.value. Display the returned page URL as a clickable link after success.
```

## Troubleshooting

### All API calls return 404 Not Found even though the Atlassian domain is correct

Cause: The base URL is missing the /wiki prefix. Confluence Cloud uses /wiki/rest/api as the API path, not /rest/api (which is Jira's path). Both services share the same atlassian.net domain but have separate URL namespaces.

Solution: Update the API Connector base URL to include /wiki: https://your-subdomain.atlassian.net/wiki/rest/api. Reinitialize all calls after updating the base URL.

### Authentication returns 401 Unauthorized even with correct credentials

Cause: The API is configured with the Atlassian account password instead of an API token. Confluence Cloud only accepts API tokens for programmatic access, not account passwords.

Solution: Generate an API token at id.atlassian.com → Security → API tokens. Use this token as the password in Bubble's Basic Auth configuration, not your Atlassian account password. The username remains your Atlassian email address.

### Initialize call fails with 'There was an issue setting up your call'

Cause: Bubble's API Connector needs a real successful API response to detect field structure during initialization. This error occurs when the API returns an error, when CQL syntax is invalid, or when default parameter values produce no results.

Solution: Enter a valid CQL query as the default value for the cql parameter before initializing. Test the CQL query in Confluence Advanced Search first to confirm it returns results. A query that returns zero results causes Bubble to fail initialization with an unhelpful error. Use a broad query like type='page' with a known space key that contains pages.

### Confluence page content shows raw HTML tags in a Bubble text element

Cause: Confluence's body.view.value field returns HTML markup. A standard Bubble text element displays this as literal text including angle brackets and tags.

Solution: Replace the standard text element with a Bubble HTML element. From the Elements panel, search for 'HTML' element type. Set the HTML element's content to the body.view.value field. The HTML element renders markup properly.

### CQL search returns no results or an error about CQL syntax

Cause: CQL is case-sensitive for field names and operators. Common mistakes include using type='Page' instead of type='page', LIKE instead of ~, and missing quotes around string values.

Solution: Verify CQL syntax in Confluence's own Advanced Search before using it in Bubble. Key rules: field names and operators are lowercase or mixed case as documented (type, text, space.key); string operators use ~ for contains and = for exact match; string values require single quotes; AND/OR are uppercase. Test the exact CQL string in Confluence first.

## Frequently asked questions

### Can I use the same Atlassian API token for both Confluence and Jira in Bubble?

Yes. Atlassian API tokens authenticate your Atlassian account across all products on your instance. The same email + API token pair works for both Confluence and Jira. However, you still need separate API Connector groups in Bubble because Confluence uses /wiki/rest/api and Jira uses /rest/api as their base URL paths — two different configurations with the same credentials.

### What is CQL and why should I use it instead of a simple keyword parameter?

CQL (Confluence Query Language) is Confluence's structured query language for searching content. It supports operators like text~ (contains), space.key= (space filter), type= (content type), ancestor= (child pages), and date comparisons. Using CQL via the /content/search endpoint is far more powerful than a basic keyword search because you can combine multiple conditions, filter by space or page hierarchy, and scope results precisely. Test your CQL queries in Confluence's Advanced Search → CQL view before using them in Bubble.

### Why do I need a Bubble HTML element to display Confluence page content?

Confluence page bodies are returned as HTML markup in the body.view.value field (when you add expand=body.view to the API call). A standard Bubble text element displays this as literal text including angle brackets and HTML tags — completely unreadable. The Bubble HTML element renders the markup into formatted content with proper headings, paragraphs, bold text, and tables.

### Does the Confluence integration work with Confluence Data Center (self-hosted) or only Confluence Cloud?

This tutorial covers Confluence Cloud only. Confluence Data Center (self-hosted) uses a different authentication mechanism and may have different API paths depending on the version. If your organization uses self-hosted Confluence, the base URL will be your internal server address, authentication may use session cookies or Personal Access Tokens (Confluence Data Center 8+), and some API endpoints may differ from Cloud.

### Is the Confluence API available on the free plan?

Yes. Confluence Cloud's free plan (up to 10 users, 2 GB storage) includes API access. The 10-user limit refers to Confluence editors and viewers, not API connections. A Bubble app reading Confluence data via the API is a single service connection, not a user seat. For teams with more than 10 users, the Confluence Cloud Standard plan at $5.75/user/month is required.

### How do I handle Confluence pagination in Bubble when there are more than 25 results?

Confluence paginates results using start (offset) and limit (page size) query parameters. Each response includes a _links.next field when more pages exist. In Bubble, implement a 'Load more' button that increments a custom state (current_page_start) by your page size (e.g., 25) and re-runs the search call with the updated start value. Show the 'Load more' button only when the previous response returned exactly 'limit' number of results.

---

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