← All migration pairs
Migration guide Generated from the live connector spec

Migrate Notion to Confluence

Confluence is a strict tree — one space, one parent per page — while Notion is a graph, and most of the work is in reconciling the two.

8entity types
53field mappings
24carry across intact
28flagged before the run

Migratly migrates Notion to Confluence by reading both APIs, deriving the mapping between them, and showing you what it found before anything is written. For this pair that is 8 entity types and 53 field mappings, of which 24 carry across intact and 28 are flagged as lossy, partial, dropped, or needing a route other than the obvious one. One of them needs a decision from you. The Notion side is read-only throughout — Migratly never writes to or deletes from your source.

How the structure changes

What maps to what

Entities are written in dependency waves. Everything at wave 0 exists before anything at wave 1 is created, which is what makes cross-references resolvable and the whole run resumable from a cursor.

NotionConfluenceWaveHow it is handledFields
Database Space 0 the collection that everything else lands in 5
User User 0 accounts matched before anything is written 4
Block InlineXHTML 1 comments, attachments and body content 3
ChildPageBlock Page 1 the records themselves 2
Page Page 1 the records themselves 28
Attachment Attachment 2 comments, attachments and body content 4
Comment FooterComment 2 comments, attachments and body content 5
Relation InlinePageLink 3 links between records, resolved last 2

Field-by-field coverage

Every mapping carries one of five labels. Full means it carries across intact. Partial means the value survives with a narrowed range. Lossy means something is lost. Workaround means there is no native slot and it is carried another way. Dropped means the target will not accept it. Anything short of full is shown to you before the run, not discovered afterwards.

Database → Space

Notion fieldConfluence fieldCoverageNotes
title name Full Notion database titles are rich_text arrays — flatten to plain text for the space name.
id key Workaround Confluence space keys are uppercase alphanumeric. Generated from the Notion database id (first 8 hex chars, prefixed with NTN).
description description Partial Notion description is rich_text — converted to a single plain paragraph for the space description.
icon no equivalent Dropped Confluence space icons are uploaded separately via /space/{key}/setting and are out of scope for v1.
properties no equivalent Workaround Notion database property schema is rendered as a Page Properties summary on each child page (per row). The schema itself is preserved as a page property on the database-parent page.

User → User

Notion fieldConfluence fieldCoverageNotes
id Original Notion User ID Lossy Confluence users are identified by accountId. Notion user IDs are preserved for audit only.
name displayName Full
person.email email Full Email is the join key. Build the Notion userId -> Confluence accountId table before any pages migrate.
type no equivalent Dropped Notion bot users have no Confluence equivalent and are filtered out.

Block → InlineXHTML

Notion fieldConfluence fieldCoverageNotes
type _xhtml_tag Partial Most Notion block types map to a clean storage XHTML element. Edge cases: synced_block flattens, button drops, equation requires Math macro app.
{block_type}.rich_text _xhtml_inline Partial Annotations bold/italic/strike/code/link map directly. Color annotations preserved via inline style. User mentions require user_mapping_table.
{block_type}.children _xhtml_nested Full Nested blocks recurse into nested XHTML containers (e.g. nested <ul> inside <li>).

ChildPageBlock → Page

Notion fieldConfluence fieldCoverageNotes
child_page.title title Full
_parent_block.page_id parentId Full

Page → Page

Notion fieldConfluence fieldCoverageNotes
id _page_property:Notion Page ID Full
properties.title title Full
parent.database_id parentId Full
parent.page_id parentId Full
_blocks body.value Partial Notion's block model is richer than Confluence storage XHTML. Most blocks convert directly; formula/rollup compute to text; synced_blocks flatten; buttons drop.
_comments no equivalent Workaround Notion comments are per-block. Confluence's API only supports page-level (footer) comments. Each Notion comment becomes one footer comment with a leading author/date line.
properties.{select} _page_property + label Full
properties.{multi_select} _labels Full
properties.{status} _page_property:Status + label Full Asks you first
properties.{date} _page_property Full
properties.{number} _page_property Full
properties.{checkbox} _page_property Full
properties.{url} _page_property + body_link Full
properties.{email} _page_property Full
properties.{phone_number} _page_property Full
properties.{people} _page_property + body_mention Partial Confluence mentions require accountId. Notion users without a matching Confluence email fall back to plain text 'Originally assigned to [name]'.
properties.{files} _attachments Partial Notion-hosted files have signed URLs that expire in 1 hour — must be downloaded and re-uploaded to Confluence during the same run. External URLs are kept as link page properties.
properties.{relation} body.value Partial Confluence has no native relation type. Each related Notion page id is rendered as an inline <ri:page> link inside the page body in a 'Related' section. Requires all pages created first.
properties.{rollup} _page_property Workaround Notion rollup logic is not reproducible in Confluence. The computed value at migration time is captured as a frozen page property.
properties.{formula} _page_property Workaround Notion formula logic is not reproducible in Confluence. The computed value at migration time is captured as a frozen page property.
created_time _page_property:Original Created Workaround Confluence createdAt is server-set. Original timestamp preserved as page property.
last_edited_time _page_property:Original Updated Workaround Confluence updatedAt is server-set on every PUT. Stored as page property for audit.
created_by.id _page_property:Original Author Workaround Confluence cannot set page author. Original Notion author preserved as page property; if a Confluence mapping exists, also rendered as an info-panel at the top of the body.
last_edited_by.id no equivalent Dropped Already covered by created_by; tracking the last editor per-page in Confluence is automatic going forward.
icon no equivalent Dropped Confluence pages have no native emoji/icon field via API. Could be rendered as a heading prefix — opt-in only.
cover no equivalent Dropped Confluence pages have no cover image field.
archived status Full
url _page_property:Original Notion URL Full

Attachment → Attachment

Notion fieldConfluence fieldCoverageNotes
file.url no equivalent Partial Notion-hosted: download bytes, then multipart upload to Confluence. External-URL files: skip rehost, render as inline link in the page body.
name filename Full
_size no equivalent Internal Used to skip files >100MB (Confluence default per-file limit).
caption _xhtml_inline Full Notion file caption rendered as the inline link/figure caption in the page body next to the attachment reference.

Comment → FooterComment

Notion fieldConfluence fieldCoverageNotes
rich_text body.value Partial Notion comments are anchored to a specific block. Confluence footer comments are anchored to the whole page — the block context is lost (unless inline-comment anchors are added in a second pass, which is out of scope for v1).
created_by.id no equivalent Workaround Confluence cannot author comments as another user. Original commenter name is prepended to the body.
created_time no equivalent Workaround Confluence comment createdAt is server-set. Original timestamp inlined into the prepended header.
discussion_id no equivalent Dropped Notion comment threads (discussion_id) have no Confluence equivalent on footer comments. Replies flatten to siblings under the same page.
parent.block_id pageId Partial Notion comments anchor to a block; we re-target the comment to the block's page. The exact in-page location is not preserved.

Relation → InlinePageLink

Notion fieldConfluence fieldCoverageNotes
relation[].id body.value._related_section Partial Confluence has no relation type. Each related Notion page id resolves to a Confluence page; inline links are appended under a 'Related' heading. No back-relation is created.
_property_name body.value._related_section.heading Full Notion lets multiple relation properties exist per page (e.g. 'Blocked by', 'Related to'). Each becomes its own subheading in the Related section so the original semantics are preserved.

What does not carry across cleanly

These are the 28 mappings where Confluence cannot hold what Notion holds. Each one appears in your coverage report with the same reason, and with the alternative routes available.

Decisions you will be asked to confirm

Migratly stops and asks rather than guessing when the right answer depends on your instance.

How a Notion to Confluence migration runs

  1. Connect both systems. Notion is connected read-only. Migratly never writes to, archives or deletes anything on the source side.
  2. Schema discovery. Both APIs are read live, including your custom fields, so the mapping reflects your instance rather than a generic Notion instance.
  3. Coverage report. All 53 mappings are presented with their coverage. You confirm, reroute or exclude before anything is written.
  4. Execution in 4 waves. Writes are idempotent and cursor-tracked, so an interrupted run resumes instead of restarting or duplicating.
  5. Verification. The result is checked back against the source, and every action is in an append-only audit log.

Questions

Can Migratly migrate Notion to Confluence?

Yes. Notion to Confluence is a supported pair with a mapping covering 8 entity types and 53 fields. You connect both systems, Migratly reads the live schemas on each side, and it produces a coverage report you approve before any data moves.

What is lost when migrating from Notion to Confluence?

28 of the 53 field mappings for this pair are flagged rather than clean. For example, `id` is marked lossy: Confluence users are identified by accountId. Notion user IDs are preserved for audit only. Every flagged mapping appears in the coverage report before the run, with its reason and the routes still open to it. Nothing is dropped silently.

How long does a Notion to Confluence migration take?

It is bounded by the two APIs' rate limits rather than by Migratly. This pair runs in 4 dependency waves, starting with account matching and ending with cross-references, and every wave is resumable — a run interrupted halfway continues from its cursor rather than starting over or duplicating what it already wrote.

Is my Notion data modified during the migration?

No. The source is read-only for the entire run. Migratly never writes to, archives, or deletes anything in Notion, and every action taken against Confluence is written to an append-only audit log.

Can a Notion database be migrated to Confluence?

Yes. Confluence has no database object, so the database becomes a parent page and each row becomes a child page beneath it. Database properties become page properties or labels depending on their type.

Do Notion page links still work after migrating to Confluence?

Yes. Inline mentions and page links are rewritten to Confluence ri:page references in a resolution pass that runs after every page exists, which is what makes circular and forward references resolvable.

What Notion content does not convert to Confluence?

Blocks with no Confluence equivalent — synced blocks, embedded databases and some third-party embeds — are the usual gaps. Every one is listed in the coverage report before the run, so nothing is discovered after the fact.

Other migration pairs