> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nekt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Confluence as a data source

> Bring spaces, pages and blog posts (with their content), comments, attachments, labels, page history, tasks, users and groups from Confluence Cloud to Nekt.

Confluence is Atlassian's team workspace and wiki, where teams create, organize and share pages, blog posts and documents in spaces. This connector reads your Confluence Cloud site through the official REST API and brings your spaces, pages and blog posts with their content and version, footer and inline comments, attachment details, labels, page edit history, tasks, users and groups.

> [!NOTE]
>
> The connector only reads data. It never creates, changes or deletes anything in Confluence. It sees exactly what the Atlassian account you connect can see: spaces and pages that account cannot view are not synced.

## Configuring Confluence as a Source

In the [Sources](https://app.nekt.ai/sources) tab, click on the "Add source" button located on the top right of your screen. Then, select the **Confluence** option from the list of connectors.

Click **Next** and you'll be prompted to add your access.

### 1. Add account access

The connector signs in with the **e-mail** of an Atlassian account and an **API token** of that account. To create the token, sign in to [id.atlassian.com](https://id.atlassian.com/manage-profile/security/api-tokens) with that account, open **Security** > **API tokens**, click **Create API token**, give it a name (for example, "Nekt") and an expiration date, and copy the token when it is shown. See [Atlassian's guide](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) for details.

> [!TIP]
>
> Use an account that can view every space you want to sync (a dedicated account for integrations works well). The data in Nekt follows that account's permissions in Confluence.

The following configurations are available:

* **Confluence Site URL**: The address of your Confluence Cloud site, as shown in the browser, for example `https://your-company.atlassian.net`.
* **E-mail**: The e-mail of the Atlassian account that created the API token.
* **API Token**: The API token. A regular token (**Create API token**) works as is. A token created with **Create API token with scopes** needs the read scopes of the tables you select (see [Permissions and scopes](#permissions-and-scopes)).
* **Body Format** (advanced, optional): The format of the content of pages, blog posts, comments and tasks. **storage** (default) is Confluence's XHTML; **atlas\_doc\_format** is the Atlassian Document Format (JSON); **none** syncs only the metadata, without the content, which makes syncs faster. When empty, storage is used.

Once you're done, click **Next**.

### 2. Select streams

Choose which data streams you want to sync. For faster extractions, select only the streams that are relevant to your analysis.

> Tip: The stream can be found more easily by typing its name.

Select the streams and click **Next**.

### 3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.

* **Layer**: choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
* **Folder**: a folder can be created inside the selected layer to group all tables being created from this new data source.
* **Table name**: we suggest a name, but feel free to customize it. You have the option to add a **prefix** to all tables at once and make this process faster!
* **Sync Type**: you can choose between INCREMENTAL and FULL\_TABLE.
  * Incremental: every time the extraction happens, we'll get only the new data, which is good if, for example, you want to keep every record ever fetched.
  * Full table: every time the extraction happens, we'll get the current state of the data, which is good if, for example, you don't want to have deleted data in your catalog.

Once you are done configuring, click **Next**.

### 4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters.

To define your [Trigger](https://docs.nekt.com/runs/scheduling-and-triggers.md), consider how often you want data to be extracted from this source. This decision usually depends on how frequently you need the new table data updated (every day, once a week, or only at specific times).

Optionally, you can define some additional settings:

* Configure Delta Log Retention and determine for how long we should store old states of this table as it gets updated. Read more about this resource [here](https://docs.nekt.com/get-started/core-concepts/resource-control).
* Determine when to execute an **Additional [Full Sync](https://docs.nekt.com/get-started/core-concepts/types-of-sync#additional-full-sync)**. This will complement the incremental data extractions, ensuring that your data is completely synchronized with your source every once in a while. For Confluence it keeps the Pages, Blog Posts and Attachments tables in line with content moved to the trash, archived, moved or permanently deleted (see [Implementation notes](#implementation-notes)).

When you are ready, click **Next** to finalize the setup.

### 5. Check your new source

You can view your new source on the [Sources](https://app.nekt.ai/sources) page. If needed, manually trigger the source extraction by clicking on the arrow button. Once executed, your data will appear in your Catalog.

> [!WARNING]
>
> For you to be able to see it on your [Catalog](https://app.nekt.ai/catalog), you need at least one successful source run.

> [!NOTE]
>
> **Page Versions** and **Content Labels** are **not selected by default** because they make many requests: Page Versions asks for the history of every page on the first sync (and, after that, only of the pages edited since the last sync), and Content Labels asks three lists per label on every sync. Select them only if you need them.

## Permissions and scopes

The connector reads what the connected account can view. A table the account cannot read is skipped with a warning in the sync log naming the table and what is missing, and the other tables keep syncing; the sync fails only when none of the selected tables can be read or the e-mail and API token are rejected.

If you use a **token with scopes**, give it these read scopes (only those of the tables you select):

| Table | Scope |
| :- | :- |
| Spaces | `read:space:confluence` |
| Content Metadata | `read:page:confluence`, `read:attachment:confluence` |
| Pages, Blog Posts, Page Versions | `read:page:confluence` |
| Footer Comments, Inline Comments | `read:comment:confluence` |
| Attachments | `read:attachment:confluence` |
| Labels | `read:label:confluence` |
| Content Labels | `read:label:confluence`, `read:page:confluence`, `read:attachment:confluence` |
| Tasks | `read:task:confluence` |
| Users | `read:content-details:confluence` |
| Groups | `read:confluence-groups` (or the granular `read:group:confluence`) |
| Group Members | `read:confluence-groups` (or the granular `read:group:confluence` and `read:user:confluence`) |

## Fields by stream

### Content

> [accordion] Spaces
>
> Spaces the account can view, current and archived.
>
> Table: `spaces` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the space. |
> | `key` | String | Space key (the short code in space URLs). |
> | `name` | String | Name of the space. |
> | `type` | String | Type of the space: global, collaboration, knowledge\_base, personal... |
> | `status` | String | Status of the space: current or archived. |
> | `description` | String | Space description as plain text. |
> | `homepage_id` | String | Identifier of the space's home page. |
> | `author_id` | String | Atlassian account ID of the user who created the space. |
> | `space_owner_id` | String | Atlassian account ID of the user who owns the space. |
> | `current_active_alias` | String | Currently active alias of the space (used in URLs). |
> | `created_at` | Datetime | When the space was created (UTC). |
> | `webui_link` | String | Path of the space in Confluence, relative to `https://<site>/wiki`. |

> [accordion] Pages
>
> Pages with their current content and version, including archived pages and pages in the trash.
>
> Table: `pages` · Primary key: `id` · Sync: Incremental on `last_modified_at`
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the page. |
> | `title` | String | Title of the page. |
> | `status` | String | Status of the page: current, archived or trashed. |
> | `space_id` | String | Identifier of the space the page belongs to. |
> | `parent_id` | String | Identifier of the parent page (or folder, whiteboard, database); empty for a top-level page. |
> | `parent_type` | String | Type of the parent: page, folder, whiteboard, database or embed. |
> | `position` | Integer | Position of the page among its siblings in the page tree. |
> | `subtype` | String | Page subtype (live for live docs, empty for regular pages). |
> | `author_id` | String | Atlassian account ID of the user who created the page. |
> | `owner_id` | String | Atlassian account ID of the user who owns the page. |
> | `last_owner_id` | String | Atlassian account ID of the previous owner. |
> | `created_at` | Datetime | When the page was created (UTC). |
> | `version_number` | Integer | Number of the current version (1 for a page never edited). |
> | `last_modified_at` | Datetime | When the current version was saved, i.e. the last edit (UTC). |
> | `version_message` | String | Message the author wrote when saving the current version. |
> | `version_minor_edit` | Boolean | Whether the current version was a minor edit (no notifications sent). |
> | `version_author_id` | String | Atlassian account ID of the user who saved the current version. |
> | `body_format` | String | Format of `body`: storage or atlas\_doc\_format (empty when **Body Format** is none). |
> | `body` | String | Content of the page in that format (XHTML or ADF JSON as text). |
> | `webui_link` | String | Path of the page in Confluence, relative to `https://<site>/wiki`. |
> | `tinyui_link` | String | Short link path of the page, relative to `https://<site>/wiki`. |

> [accordion] Blog Posts
>
> Blog posts with their current content and version, including posts in the trash.
>
> Table: `blog_posts` · Primary key: `id` · Sync: Incremental on `last_modified_at`
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the blog post. |
> | `title` | String | Title of the blog post. |
> | `status` | String | Status of the blog post: current or trashed. |
> | `space_id` | String | Identifier of the space the blog post belongs to. |
> | `author_id` | String | Atlassian account ID of the user who created the blog post. |
> | `created_at` | Datetime | When the blog post was created (UTC). |
> | `version_number` | Integer | Number of the current version. |
> | `last_modified_at` | Datetime | When the current version was saved (UTC). |
> | `version_message` | String | Message the author wrote when saving the current version. |
> | `version_minor_edit` | Boolean | Whether the current version was a minor edit. |
> | `version_author_id` | String | Atlassian account ID of the user who saved the current version. |
> | `body_format` | String | Format of `body`: storage or atlas\_doc\_format (empty when **Body Format** is none). |
> | `body` | String | Content of the blog post in that format. |
> | `webui_link` | String | Path of the blog post in Confluence, relative to `https://<site>/wiki`. |
> | `tinyui_link` | String | Short link path of the blog post. |

> [accordion] Content Metadata
>
> Where every page, blog post and attachment is now: its status, space, parent, position and owner, without the content. Read in full on every sync, so it always reflects pages moved to the trash, archived, moved in the page tree or given to another owner, which the incremental tables only see when the content is edited again. Join it with Pages, Blog Posts or Attachments on `content_type` and `id`.
>
> Table: `content_metadata` · Primary key: `content_type`, `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `content_type` | String | page, blogpost or attachment. |
> | `id` | String | Identifier of the page, blog post or attachment. |
> | `title` | String | Title (file name for attachments). |
> | `status` | String | Current status: current, archived or trashed. |
> | `space_id` | String | Space of the page or blog post (empty for attachments). |
> | `parent_id` | String | Pages: the parent page (or folder, whiteboard, database). Attachments: the page or blog post the file is attached to. |
> | `parent_type` | String | Type of the parent: page, folder, whiteboard, database, embed or blogpost. |
> | `position` | Integer | Position of the page among its siblings in the page tree. |
> | `author_id` | String | Atlassian account ID of the user who created the content. |
> | `owner_id` | String | Atlassian account ID of the current owner of the page. |
> | `last_owner_id` | String | Atlassian account ID of the previous owner of the page. |
> | `version_number` | Integer | Number of the current version. |
> | `last_modified_at` | Datetime | When the current version was saved (UTC). |

> [accordion] Page Versions
>
> Edit history: one row per saved version of every page (who saved it, when and with which message; not the content of old versions). Not selected by default.
>
> Table: `page_versions` · Primary key: `page_id`, `version_number` · Sync: Incremental on `created_at`
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `page_id` | String | Identifier of the page. |
> | `version_number` | Integer | Version number (1 = the first saved version). |
> | `created_at` | Datetime | When the version was saved (UTC). |
> | `message` | String | Message the author wrote when saving the version. |
> | `minor_edit` | Boolean | Whether the version was a minor edit. |
> | `author_id` | String | Atlassian account ID of the user who saved the version. |

> [accordion] Tasks
>
> Action items (checkbox tasks) written in pages and blog posts.
>
> Table: `tasks` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the task. |
> | `local_id` | String | Identifier of the task inside its page or blog post. |
> | `space_id` | String | Identifier of the space the task is in. |
> | `page_id` | String | Identifier of the page the task is in (empty when it is in a blog post). |
> | `blog_post_id` | String | Identifier of the blog post the task is in (empty when it is in a page). |
> | `status` | String | Status of the task: complete or incomplete. |
> | `created_by` | String | Atlassian account ID of the user who created the task. |
> | `assigned_to` | String | Atlassian account ID of the user the task is assigned to. |
> | `completed_by` | String | Atlassian account ID of the user who completed the task. |
> | `created_at` | Datetime | When the task was created (UTC). |
> | `updated_at` | Datetime | When the task was last updated (UTC). |
> | `due_at` | Datetime | Due date of the task (UTC). |
> | `completed_at` | Datetime | When the task was completed (UTC). |
> | `body_format` | String | Format of `body` (empty when **Body Format** is none). |
> | `body` | String | Text of the task in that format. |

### Comments and attachments

> [accordion] Footer Comments
>
> Comments at the bottom of pages, blog posts and attachments, replies included.
>
> Table: `footer_comments` · Primary key: `id` · Sync: Incremental on `last_modified_at`
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the comment. |
> | `status` | String | Status of the comment (current, trashed...). |
> | `title` | String | Title of the comment (usually "Re: " + the content title). |
> | `page_id` | String | Page the comment is on (empty otherwise). |
> | `blog_post_id` | String | Blog post the comment is on (empty otherwise). |
> | `attachment_id` | String | Attachment the comment is on (empty otherwise). |
> | `custom_content_id` | String | Custom content the comment is on (empty otherwise). |
> | `parent_comment_id` | String | Comment this one replies to (empty for a top-level comment). |
> | `version_number` | Integer | Number of the current version of the comment. |
> | `last_modified_at` | Datetime | When the current version was saved (UTC). |
> | `version_message` | String | Message saved with the current version. |
> | `version_minor_edit` | Boolean | Whether the current version was a minor edit. |
> | `version_author_id` | String | Atlassian account ID of the user who saved the current version. |
> | `body_format` | String | Format of `body` (empty when **Body Format** is none). |
> | `body` | String | Text of the comment in that format. |
> | `webui_link` | String | Path of the comment in Confluence, relative to `https://<site>/wiki`. |

> [accordion] Inline Comments
>
> Comments attached to highlighted text of pages and blog posts, with their resolution status.
>
> Table: `inline_comments` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the comment. |
> | `status` | String | Status of the comment. |
> | `title` | String | Title of the comment. |
> | `page_id` | String | Page the comment is on (empty otherwise). |
> | `blog_post_id` | String | Blog post the comment is on (empty otherwise). |
> | `parent_comment_id` | String | Comment this one replies to (empty for a top-level comment). |
> | `version_number` | Integer | Number of the current version of the comment. |
> | `last_modified_at` | Datetime | When the current version was saved (UTC). |
> | `version_message` | String | Message saved with the current version. |
> | `version_minor_edit` | Boolean | Whether the current version was a minor edit. |
> | `version_author_id` | String | Atlassian account ID of the user who saved the current version. |
> | `body_format` | String | Format of `body` (empty when **Body Format** is none). |
> | `body` | String | Text of the comment in that format. |
> | `webui_link` | String | Path of the comment in Confluence. |
> | `resolution_status` | String | open, reopened, resolved, or dangling (the highlighted text was removed). |
> | `resolution_last_modifier_id` | String | Atlassian account ID of the user who last resolved or reopened the comment. |
> | `resolution_last_modified_at` | Datetime | When the resolution status last changed (UTC). |
> | `inline_original_selection` | String | Text highlighted when the comment was created, when Confluence returns it. |
> | `inline_marker_ref` | String | Reference of the highlight in the page content, when Confluence returns it. |

> [accordion] Attachments
>
> Details of the files attached to pages and blog posts (the files themselves are not downloaded).
>
> Table: `attachments` · Primary key: `id` · Sync: Incremental on `last_modified_at`
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the attachment. |
> | `title` | String | File name. |
> | `status` | String | Status of the attachment: current, archived or trashed. |
> | `page_id` | String | Page the file is attached to (empty otherwise). |
> | `blog_post_id` | String | Blog post the file is attached to (empty otherwise). |
> | `custom_content_id` | String | Custom content the file is attached to (empty otherwise). |
> | `media_type` | String | Media (MIME) type of the file, e.g. application/pdf. |
> | `media_type_description` | String | Human-readable description of the media type. |
> | `comment` | String | Comment written when the file was uploaded. |
> | `file_id` | String | File identifier referenced in atlas\_doc\_format content. |
> | `file_size` | Integer | Size of the file in bytes. |
> | `created_at` | Datetime | When the file was first uploaded (UTC). |
> | `version_number` | Integer | Number of the current version of the file. |
> | `last_modified_at` | Datetime | When the current version was uploaded (UTC). |
> | `version_message` | String | Message saved with the current version. |
> | `version_minor_edit` | Boolean | Whether the current version was a minor edit. |
> | `version_author_id` | String | Atlassian account ID of the user who uploaded the current version. |
> | `webui_link` | String | Path of the attachment in Confluence, relative to `https://<site>/wiki`. |
> | `download_link` | String | Download path of the file, relative to `https://<site>/wiki` (requires signing in). |

### Labels

> [accordion] Labels
>
> Labels (tags) used on the site.
>
> Table: `labels` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the label. |
> | `name` | String | Name of the label. |
> | `prefix` | String | Label prefix: global (regular labels), my (personal), team or system. |

> [accordion] Content Labels
>
> Which label is on which page, blog post or attachment: one row per label and content. Not selected by default.
>
> Table: `content_labels` · Primary key: `label_id`, `content_type`, `content_id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `label_id` | String | Identifier of the label. |
> | `label_name` | String | Name of the label. |
> | `label_prefix` | String | Prefix of the label. |
> | `content_type` | String | Type of the labelled content: page, blogpost or attachment. |
> | `content_id` | String | Identifier of the labelled page, blog post or attachment. |
> | `content_title` | String | Title of the labelled content. |
> | `space_id` | String | Space of the labelled page or blog post (empty for attachments). |

### People

> [accordion] Users
>
> Users of the site (licensed users and guests).
>
> Table: `users` · Primary key: `account_id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `account_id` | String | Atlassian account ID of the user. |
> | `account_type` | String | atlassian (a person) or app (a bot user of an app). |
> | `display_name` | String | Display name (depending on the user's privacy settings, it may equal the public name). |
> | `public_name` | String | Public name or nickname. |
> | `email` | String | E-mail; empty when the user's privacy settings hide it. |
> | `time_zone` | String | Time zone of the user, when visible. |
> | `is_guest` | Boolean | Whether the user is a guest. |
> | `user_type` | String | Kind of user record (known, unknown, anonymous, user). |
> | `profile_picture_path` | String | Path of the profile picture, relative to the site. |

> [accordion] Groups
>
> User groups of the site.
>
> Table: `groups` · Primary key: `id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `id` | String | Unique identifier of the group. |
> | `name` | String | Name of the group. |
> | `type` | String | Kind of record (always group). |
> | `usage_type` | String | USERBASE\_GROUP (a regular group) or TEAM\_COLLABORATION (a team). |
> | `managed_by` | String | Who manages the membership: ADMINS, EXTERNAL, TEAM\_MEMBERS or OPEN. |

> [accordion] Group Members
>
> Who is in each group: one row per group and user.
>
> Table: `group_members` · Primary key: `group_id`, `account_id` · Sync: Full table
>
> | Field | Type | Description |
> | :- | :- | :- |
> | `group_id` | String | Identifier of the group. |
> | `group_name` | String | Name of the group. |
> | `account_id` | String | Atlassian account ID of the member. |
> | `account_type` | String | atlassian or app. |
> | `display_name` | String | Display name of the member. |
> | `public_name` | String | Public name of the member. |
> | `email` | String | E-mail of the member, when visible. |
> | `time_zone` | String | Time zone of the member, when visible. |
> | `is_guest` | Boolean | Whether the member is a guest. |
> | `user_type` | String | Kind of user record. |

## Implementation notes

* **Incremental tables.** Pages, blog posts, footer comments and attachments are read in full on the first sync (and on full syncs). After that, each sync reads only what changed since the previous one (re-reading the last hour), based on the date of the last edit.
* **Content.** The **body** column holds the content in the format chosen in **Body Format**, as text. Confluence's XHTML (storage) keeps macros and formatting; to analyze plain text, strip the tags in a Query or Notebook.
* **Inline comments, tasks, labels, users and groups** are read in full on every sync: resolving an inline comment, adding a label, or completing a task does not change anything Confluence lets the connector filter by.
* **Trash, archive, moves and owners.** Moving content to the trash, archiving it, moving a page in the page tree or changing its owner does not create a new version in Confluence, so the incremental tables (Pages, Blog Posts, Attachments) keep the previous status, parent and owner until the content is edited again. Use the **Content Metadata** table, read in full on every sync, for the current values, or schedule an **Additional Full Sync** (for example weekly) to refresh the incremental tables. Content permanently deleted from the trash leaves Content Metadata on the next sync and stays in the incremental tables until a full sync.
* **Users.** Confluence lists at most 10,000 users through its API; the sync log warns when a site reaches that limit. E-mails are often empty because of the users' privacy settings.
* **Safety.** Full-table streams are read completely before anything is written to Nekt, so a sync that fails halfway does not replace them with partial data; if one that had records comes back empty (for example, after the account lost access), that table fails instead of being emptied; run a full sync of the source if the data really was removed. Incremental tables are written as they are read and only move their sync position forward when the read is complete, so a failed sync is read again on the next one.
* **Speed.** Requests are sent one at a time and the connector waits when Confluence asks it to slow down, which the sync log shows. Choosing **none** in **Body Format** makes syncs much lighter when you only need metadata.

## Troubleshooting

| Error or symptom | What it means | What to do |
| :- | :- | :- |
| "Confluence rejected the e-mail and API token" | The token is wrong, revoked or expired, or the e-mail is not the token owner's. | Create a new API token with the same account and update **E-mail** and **API Token**. |
| "does not point to an existing Atlassian Cloud site" | The **Confluence Site URL** is wrong. | Copy the site address from the browser (for example `https://your-company.atlassian.net`). |
| "may not use Confluence on this site" | The account has no access to Confluence on that site. | Ask a site administrator to give the account access to Confluence. |
| A table is skipped with "lacks the scope" | The token with scopes does not include the scope of that table. | Create a token with the scopes listed in [Permissions and scopes](#permissions-and-scopes), or deselect the table. |
| A table is skipped with "the account needs..." | The account cannot read that data. | Give the account the permission named in the message, or deselect the table. |
| Some pages or spaces are missing | The account has no view permission on them. | Give the account view access to those spaces (and pages with restrictions). |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.