Skip to content

Document360 to Confluence Migration: The Complete Technical Guide

Document360 to Confluence migration requires converting Markdown/HTML to Confluence Storage Format, handling API limits, and rewriting every internal link.

Raaj Raaj · · 30 min read
Document360 to Confluence Migration: The Complete Technical Guide
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

There is no native, one-click path for a Document360 to Confluence migration. Document360 exports articles as .md, .html, or .json depending on editor type and language selection. Confluence requires content in its proprietary Storage Format (an XHTML-based XML dialect with custom macro elements) or Atlassian Document Format (ADF, a JSON schema). The Confluence REST API rejects raw Markdown and standard HTML — push Document360's raw export to the API and the request will fail. (confluence.atlassian.com)

The real work in this migration is format conversion, media handling, and link rewriting. This guide covers what can and cannot be migrated, the exact data-mapping decisions you will face, the API rate limits on both sides, and the edge cases that cause silent data loss.

Confluence Cloud does offer a native HTML import flow under Import from other tools. It accepts a ZIP of .html files, creates a new space, and uses filenames as page names. But it has significant limitations: it cannot process Markdown or multilingual JSON exports, code blocks degrade to plain text, iframes are unsupported, and Atlassian does not document a folder-to-page-tree convention for deep hierarchies. For Document360 workspaces with Markdown articles, mixed editor types, or heavy cross-linking, the HTML importer is only part of the job. (support.atlassian.com)

Warning

Do not confuse Confluence's two import flows. The older document importer handles Word, Google Docs, and OneDrive files in batches of up to 30 files and 50 MB total. The newer HTML importer is a separate flow that creates a new space from a ZIP of HTML files. They have different limits and different behavior. (support.atlassian.com)

Migration Path Fidelity Format Conversion Attachments Link Rewriting Best For
Manual copy-paste Low Manual Manual re-upload Under 20 articles
Confluence HTML import Low–Medium Partial (HTML only) Page-matched folders Small, HTML-only, low-metadata projects
ZIP export → Marketplace importer Low–Medium Partial ❌ (inline images break) Text-heavy articles, minimal media
DIY API scripts Medium–High ✅ (custom parser) ✅ (separate pipeline) ✅ (custom) Engineering teams with time
ClonePartner managed migration Highest ✅ (automated) Complex knowledge bases, zero downtime

For a detailed breakdown of Confluence's native import capabilities and limits, see How to Import Data into Confluence: Methods, API Limits & Mapping.

High-Level Workflow: Extract → Transform → Load

Every Document360-to-Confluence migration follows the same three-phase pattern, regardless of whether you script it yourself or use a managed service:

  1. Extract — Pull content, metadata, and media out of Document360 via the REST API or ZIP export.
  2. Transform — Convert Markdown/HTML to Confluence Storage Format (or ADF), rewrite internal links, rename duplicate titles, and map the category hierarchy to a Confluence page tree.
  3. Load — Push pages, attachments, labels, and permissions into Confluence via the REST API, respecting rate limits and handling failures with retry logic.

Each phase has its own failure modes. Extraction can hit Document360's rate limits or miss content locked behind editor-type differences. Transformation is where most data loss happens — a malformed Storage Format tag silently drops content. Loading must handle Confluence's own rate limits, title uniqueness constraints, and attachment upload ordering. The rest of this guide walks through each phase in detail.

Why Migrating Document360 to Confluence is Different

Migrating Document360 to Confluence is not a standard export-import job. Document360 allows mixed formats within the same project—some articles are Markdown, some are HTML, and multilingual exports are JSON. Confluence strictly requires its proprietary Storage Format (XHTML-based XML) or Atlassian Document Format (ADF). If you push raw Document360 exports to the Confluence API, they will fail. You must build a translation layer that handles format conversion, attachment re-linking, and internal link rewriting simultaneously.

Quick Checklist: Document360 to Confluence Migration

Before starting, ensure you have a plan for these core requirements:

  • Export Strategy: Determine if you will use the ZIP export (UI) or the API (requires Enterprise plan for bulk export).
  • Format Conversion: Build or buy a parser to convert .md and .html to Confluence Storage Format.
  • Attachments: Download all media from Document360's CDN and upload them as Confluence page attachments.
  • Link Rewriting: Map old Document360 slugs to new Confluence Page IDs and update all internal links.
  • Title Deduplication: Confluence requires unique page titles within a Space; Document360 does not. Plan your renaming logic.
  • Redirect Mapping: Plan how to redirect old Document360 URLs to new Confluence URLs post-migration.
  • Rollback Plan: Know how to clean up partially migrated content in Confluence if something fails.

Supported Export Formats from Document360

Document360 offers two primary extraction paths, each with different format outputs and coverage:

ZIP export (UI or Enterprise API)

  • Markdown articles export as .md files
  • WYSIWYG / Advanced WYSIWYG articles export as .html files
  • Multilingual projects export as .json (all languages bundled per article)
  • Includes a JSON manifest mapping the category-article hierarchy
  • Includes a Media folder with all referenced images and files
  • UI export allows scoping by modified date, workspace, language, and category
  • The export-project API endpoint is Enterprise-only and limited to twice per day

(docs.document360.com)

REST API extraction (per-article)

  • Returns article content via GET /v2/Articles/{articleId}/{langCode}
  • The editor_type field indicates the format: 0 = Markdown, 1 = WYSIWYG, 2 = Advanced WYSIWYG
  • Setting isForDisplay=true expands snippets and variables into rendered content
  • Setting isForDisplay=false returns raw tokens (snippets/variables unexpanded)
  • Setting appendSASToken=false prevents SAS-signed CDN URLs in the output
  • Available on Professional plans and above (Standard has no API access)

(apidocs.document360.com)

Confluence import options

On the Confluence side, you have two main paths for loading content:

Method Format Required Best For Limitations
REST API (v1) Storage Format (XHTML) Full-fidelity programmatic migration Must build converter; rate limits apply
REST API (v2) Atlassian Document Format (ADF, JSON) New tooling, future-proof integrations ADF schema is more complex; less community tooling available
HTML importer ZIP of .html files Quick, small, HTML-only migrations No Markdown support; code blocks degrade; no link rewriting; creates a new space

The REST API is the only path that gives you full control over hierarchy, attachments, labels, and link rewriting.

The Format Conversion Challenge: Markdown/HTML to Confluence Storage Format

This is the single biggest technical hurdle, and most teams underestimate it.

Document360's export format depends on which editor was used to create each article. Articles from the Markdown editor export as .md files. Articles from the WYSIWYG or Advanced WYSIWYG editor export as .html files. If you export a multilingual project, Document360 outputs everything as .json. A single knowledge base can contain a mix of all three. (docs.document360.com)

Confluence does not accept any of these formats natively. Atlassian's content-body conversion APIs handle conversions between storage, atlas_doc_format, and editor-related representations — not from raw Markdown or arbitrary HTML. The API requires the page body in one of two representations:

  1. Storage Format — XHTML-based XML with custom <ac:> and <ri:> elements for macros, links, and embedded resources
  2. Atlassian Document Format (ADF) — a JSON schema used by the v2 API

A simple Markdown heading like ## Getting Started becomes <h2>Getting Started</h2> in Storage Format. That is the trivial part. The hard part is everything else:

Element Document360 Format Confluence Storage Format
Code blocks Standard backticks (```) <ac:structured-macro ac:name="code"> with CDATA body
Tables Pipe syntax (| col |) or HTML <table> <table> with specific class attributes
Internal links Slugs or href URLs <ac:link> with <ri:page> referencing title and space key
Inline images <img src="..."> or ! [alt](url) <ac:image><ri:attachment ri:filename="..."/></ac:image>
Callouts HTML/Markdown variants <ac:structured-macro ac:name="info"> or similar

Macro and Callout Conversion Rules

Document360 callouts and special blocks must be converted to Confluence structured macros. Here are the specific mappings:

Document360 Element Confluence Macro Storage Format
Info callout / note Info macro <ac:structured-macro ac:name="info">
Warning callout Warning macro <ac:structured-macro ac:name="warning">
Tip / success callout Tip macro <ac:structured-macro ac:name="tip">
Danger / error callout Note macro (with title) <ac:structured-macro ac:name="note">
Code block with language Code macro <ac:structured-macro ac:name="code">
Table of contents TOC macro <ac:structured-macro ac:name="toc"/>
Embedded video / iframe Widget connector or multimedia macro <ac:structured-macro ac:name="widget">

Here is a concrete example. A callout block in Document360's HTML:

<!-- Document360 HTML callout -->
<div class="callout callout-warning">
  <p>This API endpoint is deprecated and will be removed in v3.</p>
</div>

Must become this in Confluence Storage Format:

<ac:structured-macro ac:name="warning" ac:schema-version="1">
  <ac:rich-text-body>
    <p>This API endpoint is deprecated and will be removed in v3.</p>
  </ac:rich-text-body>
</ac:structured-macro>

A code block extracted from Document360:

```javascript
console.log("Hello World");

Must become this in Confluence Storage Format:

```xml
<ac:structured-macro ac:name="code" ac:schema-version="1">
  <ac:parameter ac:name="language">javascript</ac:parameter>
  <ac:plain-text-body><![CDATA[console.log("Hello World");]]></ac:plain-text-body>
</ac:structured-macro>

And an internal link:

<!-- Document360 HTML -->
<a href="/docs/getting-started">Getting Started</a>
 
<!-- Confluence Storage Format -->
<ac:link>
  <ri:page ri:content-title="Getting Started" ri:space-key="DOCS" />
</ac:link>

If your parser misses a closing tag or fails to wrap special characters in CDATA blocks, Confluence rejects the entire page payload with a 400 Bad Request or 500 Internal Server Error. Confluence Storage Format is strict XML — a single unclosed tag or unescaped ampersand causes rejection of the whole page.

Building a reliable parser that handles all of these conversions — including edge cases like nested tables, mixed Markdown/HTML content, and embedded video iframes — is the bulk of the engineering work in a DIY migration.

Tip

Approach for building the converter: Parse Markdown to an AST using a library like markdown-it (JavaScript) or mistune (Python), then write a custom renderer that outputs Confluence Storage Format XML instead of standard HTML. For HTML source content, use an HTML parser like BeautifulSoup (Python) or cheerio (JavaScript) to walk the DOM and emit the corresponding Confluence macro elements. This two-track approach — one renderer for Markdown, one transformer for HTML — matches Document360's mixed-editor reality.

What Can (and Cannot) Be Migrated from Document360

What migrates

Document360 Object Migration Path Notes
Articles (body content) API or ZIP export Content must be converted to Storage Format or ADF
Categories & subcategories API or ZIP export Hierarchy preserved in the ZIP's folder structure and JSON manifest
Media files (images, PDFs) ZIP export includes a Media folder Must be re-uploaded as Confluence attachments via API
Article metadata (title, slug, order, status) API only ZIP includes order and status; API provides richer metadata
Article versioning API only (per-version retrieval) Confluence stores versions natively, but you must create them sequentially
Multilingual content API or ZIP export (per-language) Each language must be handled as a separate migration pass

What does NOT migrate

Warning

Document360's native project export explicitly excludes content reuse elements. Templates, variables, snippets, and glossary terms are not part of the export/import process and must be recreated manually. (docs.document360.com)

Document360 Object Why It Doesn't Migrate
Templates Not included in ZIP export; no API endpoint for bulk template extraction
Variables Excluded from export — rendered inline when using isForDisplay=true via API, but the variable definitions themselves are lost
Snippets Reusable content blocks are not exported as discrete objects
Glossary terms Not included in export; no direct Confluence equivalent
Article analytics (views, ratings, feedback) Not exportable; Document360 analytics are platform-specific
Workflow status assignments Workflow metadata is not included in the export ZIP
Reader accounts & permissions User/reader data does not transfer; Confluence uses its own permission model
Custom domain / SEO settings Platform-specific configuration
API documentation (OpenAPI specs) Interactive API docs are a separate Document360 module with no Confluence parallel

If your documentation relies heavily on Document360 snippets or variables, you have a choice when extracting via API. Setting isForDisplay=true expands snippets and variables into the article body, giving you the rendered version that matches what readers see. Setting isForDisplay=false returns raw tokens that will not render in Confluence. The rendered version is usually the safer choice for migration fidelity, but you lose the ability to recreate reusable content blocks on the Confluence side. Also set appendSASToken=false so you do not accidentally migrate SAS-signed asset URLs into Confluence. (apidocs.document360.com)

Danger

WebHelp export is already lossy. Document360's HTML5 WebHelp export includes search, media support, and internal links, which makes it look like a good Confluence import source. But WebHelp excludes attachments, glossary definitions, inline comments, breadcrumbs, article-level table of contents, and previous/next navigation. If attachments or glossary content matter, WebHelp is not a full-fidelity source. (docs.document360.com)

For teams evaluating the reverse direction, see Confluence to Document360 Migration: API Limits & Data Mapping Guide.

Data Mapping: Document360 Architecture → Confluence Architecture

The architectural mismatch between Document360 and Confluence is where most planning mistakes happen. Document360 organizes content as Projects → Workspaces → Categories → Articles. Confluence uses Sites → Spaces → Pages (with parent-child hierarchy).

Document360 Concept Confluence Equivalent Notes
Project Confluence Site 1:1 — each D360 project maps to a Confluence Cloud site
Workspace Space Each workspace becomes its own Confluence Space with a unique space key
Top-level Category Parent Page (under Space homepage) Categories become pages that serve as containers — add overview text or they appear blank
Subcategory Child Page (nested under parent) Confluence supports deep nesting; mirror D360's category depth
Article Page (child of its category page) Body converted to Storage Format; title preserved
Article order Page order within parent Set via the Confluence API's position parameter on v2 endpoints
Media file Attachment on the page that references it Or attach to a shared "assets" page if media is reused across articles
Article slug Page title (URL auto-generated) Confluence auto-generates URLs from titles; no custom slug support
Tags Labels Document360 tags map to Confluence labels; apply via POST /wiki/rest/api/content/{id}/label
Custom fields Page Properties or Labels Use the Page Properties macro for structured metadata that can be queried with the Page Properties Report macro
Content Snippets Page Templates or Include Page macro Snippets lose their reuse structure on export; recreate as Confluence page templates or use {include} macros referencing shared pages
Users / Teams Confluence Users / Groups No automatic mapping; provision users in Confluence separately and assign space/page permissions

Spaces cannot be nested in Confluence, but pages can be nested to arbitrary depth. The category tree belongs in the page hierarchy, not in separate spaces.

Handling hierarchy depth limits

Confluence supports deep page nesting, but extremely deep hierarchies (more than 5–6 levels) create usability problems — navigation becomes unwieldy and page trees are hard to browse. If your Document360 category structure goes deeper than this, consider these strategies:

  • Flatten the deepest levels: Merge the bottom two levels of subcategories into a single level in Confluence, using descriptive page titles to preserve context.
  • Use labels for cross-cutting organization: If categories are deeply nested because articles belong to multiple logical groups, use Confluence labels to provide alternative navigation paths without adding hierarchy depth.
  • Split into multiple spaces: If a single Document360 workspace has a very deep, broad category tree, splitting it into multiple Confluence spaces (one per major section) can reduce depth and improve navigation.

Map your Document360 category tree to the target Confluence page tree before migration. A spreadsheet or JSON mapping file that lists each category path alongside its target Confluence parent page ID makes the migration script deterministic and auditable.

The title collision problem

Document360 allows multiple articles to share the same name as long as they live in different categories. Confluence enforces a strict rule: all pages within a single Space must have a unique title. If you migrate two articles named "Authentication" into the same Confluence Space, the API will reject the second one.

Your migration logic must detect duplicate titles and apply a deterministic rename rule before import — for example, appending the category name ("Authentication - API" vs. "Authentication - SSO"). If you use the Confluence HTML importer, the same constraint applies: filenames become page names, and duplicates will collide. (support.atlassian.com)

Handling versioned projects

Document360 supports project versions (e.g., v1.0, v2.0) — separate documentation sets for different product releases. Confluence has no native equivalent. Your options:

  1. One Space per versionDOCS-V1, DOCS-V2. Clean separation, but content duplication.
  2. Version labels — Tag all pages with a label like version-2.0 and use Confluence's CQL search to filter. Less duplication, but harder to navigate.
  3. Archive older versions — Migrate only the latest version as active pages. Export older versions to PDF and attach them for reference.

Multilingual content

Document360 exposes available_languages and translation status per article. Since Confluence requires unique page names within a space, repeated titles like "Overview" or "Introduction" across languages will collide. Separate spaces per language are usually cleaner than a single multilingual space with language-root pages. (apidocs.document360.com)

Permission and access mapping

Document360 supports public vs. private knowledge bases, team-based access, and reader account restrictions. Confluence has its own permission model at two levels:

  • Space permissions: Control who can view, create, edit, or administer content within a space. Map Document360 workspace-level access to Confluence space permissions.
  • Page restrictions: Control who can view or edit individual pages. Map Document360 private/restricted articles to Confluence page-level restrictions.

Document360 reader accounts and team assignments do not export. You must provision users in Confluence (or sync from your identity provider) and then apply permissions via the Confluence REST API. Plan this mapping before migration — retroactively applying permissions across hundreds of pages is tedious and error-prone.

For teams thinking through Confluence Space architecture from other migration contexts, see SharePoint to Confluence Migration: The Complete Technical Guide.

API Rate Limits: Document360 and Confluence Constraints

Both platforms enforce rate limits that directly affect migration speed. Ignoring them does not just slow you down — it causes dropped records.

Document360 API rate limits

Rate limits are applied per api_token, and each subscription tier has different allowances (apidocs.document360.com):

  • Standard: No API access
  • Professional and Business: 60 requests per minute
  • Enterprise, Enterprise Plus, and Trial: 100 requests per minute

Every API call (GET, POST, PUT, DELETE) counts as one request. The X-RateLimit-Remaining header is included in every response by default. X-RateLimit-Limit and X-RateLimit-Reset headers only appear once the limit is reached. When exhausted, the API returns HTTP 429 and you must wait for the reset window.

If you script the project export through the API instead of the UI, there is a separate ceiling: the export-project API endpoint is Enterprise-only and can be used twice per day. That works for scheduled production exports but is terrible for trial-and-error development. (docs.document360.com)

Tip

Before starting a migration, make a few test calls and check the X-RateLimit-Remaining header to determine your actual quota. If you are migrating hundreds of articles via API on a Professional or Business plan, you may need to batch your calls across multiple reset windows.

Confluence Cloud API rate limits

Confluence Cloud uses a points-based rate-limit model with phased enforcement. Instead of counting raw requests, each API call consumes points based on operation complexity and payload size.

There is a critical distinction here that many migration guides get wrong: the points-based quotas apply to Forge, Connect, and OAuth 2.0 (3LO) apps. API token-based traffic is not subject to the new points-based quotas and remains under existing burst limits. If your migration script uses basic API tokens, you still need backoff and retry logic for 429 responses, but you do not automatically inherit the app-tier point quotas. (developer.atlassian.com)

Key constraints for migration scripts regardless of authentication method:

  • Burst limits: Per-second rate limits apply per endpoint, independent of any hourly quota. Sending too many requests per second triggers HTTP 429 even if you have quota remaining.
  • Body expansion cap: API queries that expand body.storage are limited to 50 results per request.
  • Page body size: Content bodies exceeding roughly 64 KB can trigger HTTP 400 errors.
  • 429 response handling: The Retry-After header tells you how many seconds to wait. Implement exponential backoff with jitter — do not just retry immediately.

Rate-limit orchestration and retry strategy

A migration script that does not handle rate limits gracefully will drop records. Here is a practical approach:

  1. Track remaining quota by reading X-RateLimit-Remaining on every Document360 response. When it drops below 10% of your limit, pause until the reset window.
  2. Implement exponential backoff with jitter for both platforms. On a 429 response, read the Retry-After header, add random jitter (10–20% of the wait time), and sleep before retrying.
  3. Cap concurrent requests. For Document360, serialize requests or use a concurrency limit of 1–2. For Confluence, limit to 2–3 concurrent requests per endpoint to stay under burst limits.
  4. Set a maximum retry count (e.g., 5 retries per request). After exhausting retries, log the failure with full context (article ID, endpoint, response code) and continue — do not let a single failed page halt the entire migration.
  5. Use a dead-letter queue. Failed requests go into a retry queue that you process after the main migration pass. This prevents rate-limit-induced gaps in your migrated content.
# Rate-limit-aware loop for Confluence page creation
import time
import random
import requests
 
def create_page_with_backoff(url, headers, payload, max_retries=5):
    for attempt in range(max_retries):
        resp = requests.post(url, headers=headers, json=payload)
        if resp.status_code == 200:
            return resp.json()
        elif resp.status_code == 429:
            retry_after = int(resp.headers.get("Retry-After", 60))
            jitter = random.uniform(0, retry_after * 0.1)
            print(f"Rate limited. Waiting {retry_after + jitter:.1f}s (attempt {attempt + 1}/{max_retries})")
            time.sleep(retry_after + jitter)
        else:
            resp.raise_for_status()
    raise Exception(f"Max retries exceeded for page: {payload.get('title', 'unknown')}")
Info

If you use the native HTML importer instead of the API, your limiting factor may be Confluence's attachment size setting, not a published HTML-import cap. Atlassian's FAQ tells admins to increase the attachment-size limit so it exceeds the HTML ZIP size before import. (support.atlassian.com)

For a deeper look at Confluence API behavior during large imports, see How to Import Data into Confluence: Methods, API Limits & Mapping.

These two operations cause the most silent data loss in Document360-to-Confluence migrations. Both require multi-step API workflows.

Embedded media

Document360 stores images and files on its own CDN. When you export a project as a ZIP, media files are included in a Media folder. When you use the API, article content contains CDN URLs pointing to Document360's domain.

Getting images into Confluence requires a specific sequence:

  1. Create the Confluence page (to generate a Page ID).
  2. Download the image binary from Document360 (from the ZIP or by fetching the CDN URL).
  3. Upload the file as a Confluence attachment using POST /wiki/rest/api/content/{pageId}/child/attachment with the X-Atlassian-Token: nocheck header. (developer.atlassian.com)
  4. Update the page body to reference the new attachment using Confluence's macro syntax.
# Example: Upload an attachment to a Confluence page
curl -X POST \
  "https://your-domain.atlassian.net/wiki/rest/api/content/123456/child/attachment" \
  -H "X-Atlassian-Token: nocheck" \
  -H "Authorization: Basic $(echo -n 'email@example.com:API_TOKEN' | base64)" \
  -F "file=@screenshot.png" \
  -F "comment=Migrated from Document360"
<!-- Before (Document360 HTML) -->
<img src="https://cdn.document360.io/project/images/screenshot.png" />
 
<!-- After (Confluence Storage Format) -->
<ac:image>
  <ri:attachment ri:filename="screenshot.png" />
</ac:image>

If you skip step 4, the image file will be attached to the page but will not render inline. The attachment must be uploaded to the same page that references it (or you must use cross-page attachment references, which add complexity). Confluence's default attachment size limit is 100 MB per file.

For HTML-import flows, supplemental media must live in a folder that matches the page name, and unsupported media types will be ignored. Either way, imported page content does not mean resolved media references.

Document360 articles link to each other using URL slugs (e.g., /docs/getting-started). After migration, those slugs no longer exist. Every internal link must be rewritten to point to the correct Confluence page.

The process:

  1. Build a mapping table of Document360 article IDs/slugs → Confluence page IDs.
  2. Create all pages in Confluence (with placeholder or final content).
  3. Second pass: Update each page's body, replacing Document360 link references with Confluence <ac:link> elements that reference the correct page title and space key.

This two-pass approach is necessary because you cannot reference a Confluence page that does not exist yet. The second pass consumes additional API calls (one PUT per page), so budget for this when planning around rate limits.

Danger

Common failure mode: DIY scripts that attempt a single-pass migration end up with broken internal links on every page that references another page created later in the sequence. Always plan for a two-pass approach or use a migration engine that handles deferred link resolution.

Post-migration redirect strategy

After migration, your old Document360 URLs will return 404s unless you set up redirects. This matters for SEO (preserving link equity) and for users who have bookmarked or linked to your documentation externally.

Options for handling redirects:

  • Reverse proxy or CDN rules: If your Document360 instance was on a custom domain, configure your reverse proxy (e.g., Nginx, Cloudflare) to 301-redirect old URL paths to the corresponding Confluence page URLs.
  • Document360 custom domain settings: If you control the DNS for your documentation domain, point it to a redirect service that maps old slugs to new Confluence URLs using the mapping table you built during migration.
  • Redirect map file: During migration, generate a CSV mapping every old Document360 URL to the new Confluence URL. This file feeds whatever redirect mechanism you choose.

The mapping table from Step 6 (link rewriting) is the same data you need for redirects — store the original Document360 slug and the resulting Confluence page URL together.

Step-by-Step: The API Migration Workflow

If you are building this yourself, here is the execution plan.

Step 1: Audit the source

Count workspaces, languages, category depth, editor types, reused-content features (snippets, variables), duplicate article titles, custom fields, and public/private docs. This determines whether the HTML importer is viable or whether you need a full API pipeline.

Check your Document360 plan: Standard has no API access, and the project ZIP export API endpoint is Enterprise-only. That combination can force a UI-export or service-led extraction plan. (apidocs.document360.com)

Step 2: Extract data from Document360

Use the Document360 API to pull the full category tree and all articles:

  • GET /v2/ProjectVersions → list all project versions
  • GET /v2/ProjectVersions/{versionId}/categories/{langCode} → full category tree with nested articles
  • GET /v2/Articles/{articleId}/{langCode} → individual article content

For published knowledge bases, isForDisplay=true (expand snippets and variables), isPublished=true (latest published version), and appendSASToken=false (prevent SAS-signed URLs) is the cleanest starting point. (apidocs.document360.com)

# Example: Extract a single article from Document360
curl -X GET \
  "https://apihub.document360.io/v2/Articles/{articleId}/en?isForDisplay=true&isPublished=true&appendSASToken=false" \
  -H "api_token: YOUR_D360_API_TOKEN" \
  -H "Content-Type: application/json"
# Example: Get the full category tree for a project version
curl -X GET \
  "https://apihub.document360.io/v2/ProjectVersions/{versionId}/categories/en" \
  -H "api_token: YOUR_D360_API_TOKEN" \
  -H "Content-Type: application/json"

Alternatively, use the ZIP export for bulk extraction. The ZIP contains a JSON manifest file that maps the category-article hierarchy, plus a Media folder with all referenced files. The UI export lets you scope by modified date, workspace, language, and category, and optionally include media. (docs.document360.com)

Step 3: Create the Confluence Space and page hierarchy

  • Create one Confluence Space per Document360 Workspace.
  • Create parent pages for each top-level category (include any category description text — do not leave them blank).
  • Create child pages for subcategories and articles, preserving the nesting depth.
  • Store a mapping table keyed by Document360 article ID, category ID, and URL as you create each page.
# Example: Create a Confluence page via REST API v1
curl -X POST \
  "https://your-domain.atlassian.net/wiki/rest/api/content" \
  -H "Authorization: Basic $(echo -n 'email@example.com:API_TOKEN' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "page",
    "title": "Getting Started",
    "space": {"key": "DOCS"},
    "ancestors": [{"id": "PARENT_PAGE_ID"}],
    "body": {
      "storage": {
        "value": "<p>Page content in Storage Format</p>",
        "representation": "storage"
      }
    }
  }'

Step 4: Convert content to Confluence Storage Format

For each article:

  • If Markdown: Parse with a Markdown-to-HTML library, then transform the HTML to valid Confluence Storage Format XML.
  • If HTML: Sanitize the HTML, then transform to Storage Format — replace standard HTML tags with Confluence-specific elements where needed.

Detect the editor type from the API response. The editor_type field returns 0 for Markdown, 1 for WYSIWYG, and 2 for Advanced WYSIWYG. Branch your converter accordingly. Mixed editors in a single project mean mixed pipelines.

This step must handle: headings, paragraphs, lists (including nested lists), tables, code blocks with language hints, images, links, and callout boxes.

Step 5: Upload attachments

For each page, download all referenced media files and upload them as Confluence attachments via the attachment API. Track the filename-to-page-ID mapping for the next step.

Second pass through all pages: replace Document360 CDN image URLs with <ac:image> attachment references, and replace internal article links with <ac:link> elements pointing to the correct Confluence page title and space key.

Step 7: Validate

Run a validation pass comparing:

  • Total article count in Document360 vs. total page count in Confluence
  • Attachment count per page
  • Spot-check formatting on a representative sample — prioritize pages with code blocks, tables, nested lists, inline images, and repeated titles
  • Test all internal links for 404s
Tip

Pilot with the hard cases first, not the easy ones. Pick pages with code blocks, tables, nested lists, inline images, multilingual content, and repeated titles. If you imported into a staging space, Confluence says moved items carry their attachments, comments, child items, and incoming links, and get automatic redirects. That makes staging-space validation much safer than importing directly into production. (support.atlassian.com)

Tip

Store the original Document360 article ID, category ID, URL, and last-modified date as Confluence page properties. This gives you idempotent reruns, easier QA, and a clean redirect map. (apidocs.document360.com)

Validation Checklist

After migration completes, run through this checklist before declaring success:

  • Record-count parity: Total article count in Document360 matches total page count in the target Confluence space(s). Query both APIs and compare programmatically.
  • Attachment integrity: For each page, compare the number of attachments in Confluence against the number of media references in the source article. Flag any page where the counts do not match.
  • Link rewriting verification: Run a link checker (e.g., linkchecker, a custom script, or Confluence's built-in broken-link report) across all migrated pages. Every internal link should resolve to a valid Confluence page — zero 404s.
  • Image rendering: Spot-check pages with inline images. Confirm that <ac:image> references render correctly and do not show broken-image icons or fall back to Document360 CDN URLs.
  • Code block fidelity: Open pages that contained code blocks in Document360. Verify that the code macro renders with correct syntax highlighting and that no content was lost inside CDATA sections.
  • Table structure: Check pages with complex tables (merged cells, nested content). Confirm that table structure survived the conversion without dropped rows or columns.
  • Hierarchy accuracy: Walk the Confluence page tree and compare it to the Document360 category structure. Verify parent-child relationships match the original nesting.
  • Title uniqueness: Confirm no pages were silently skipped due to title collisions. Cross-reference your migration log against the source article list.
  • Label/tag mapping: Verify that Document360 tags were applied as Confluence labels on the correct pages.
  • Permission checks: If you applied space permissions or page restrictions, verify that the correct users/groups have the expected access. Test with a non-admin account.
  • Metadata carryover: If you stored Document360 metadata (article ID, slug, last-modified date) as page properties, verify a sample to confirm the values are correct.
  • Redirect verification: If you set up URL redirects, test a sample of old Document360 URLs and confirm they 301-redirect to the correct Confluence pages.

Rollback and Cleanup Strategy

Migrations fail partway through. Plan for it.

If your migration script fails mid-run or you discover data quality issues after loading, you need a way to clean up and retry. Options:

  • Delete the entire space: If you created a dedicated Confluence space for the migration, the simplest rollback is to delete the space and start over. Use DELETE /wiki/rest/api/space/{spaceKey} — this removes all pages, attachments, and metadata in that space. This is destructive and irreversible.
  • Delete individual pages: If you need to roll back selectively, use DELETE /wiki/rest/api/content/{pageId} for each page. Deleting a parent page moves child pages to the trash as well.
  • Use the migration log: Your migration script should log every created page ID. On rollback, iterate through the log and delete in reverse order (children before parents).
  • Trash vs. permanent delete: Confluence moves deleted pages to the trash by default. They remain recoverable for the space admin. To permanently purge, empty the trash after deletion.
Warning

Always migrate into a staging space first, not your production space. Validate in staging, then either move pages to the production space or rename the staging space. This gives you a clean rollback path without risking production content.

Confluence Cloud vs. Data Center

This guide focuses on Confluence Cloud, but if your target is Confluence Data Center (Server), be aware of these differences:

  • Import options: Data Center supports XML site imports (full site or space-level backups) via the site admin console. The HTML importer is a Cloud-only feature.
  • API endpoints: Data Center uses the same REST API structure, but authentication is different (no OAuth 2.0 3LO; typically uses personal access tokens or session cookies).
  • Rate limits: Data Center does not enforce the points-based rate-limit model. Performance constraints are based on your server's hardware and JVM configuration, not Atlassian-imposed quotas.
  • Storage Format: The Storage Format is the same across Cloud and Data Center. Content converted for Cloud will work on Data Center without modification.
  • Marketplace apps: Some import apps are Cloud-only or Data Center-only. Verify compatibility before purchasing.

If you are migrating to Data Center, the extraction and transformation steps in this guide still apply. The loading step changes — you may use the REST API, or you may build a Confluence XML export package and import it through the admin console.

Edge Cases That Cause Silent Data Loss

  • Mixed editor types in a single project. Single-language exports can contain both .md and .html files. Multilingual exports become .json. One parser will not cover every scenario — your converter must detect the editor type and branch accordingly. (docs.document360.com)

  • Variables and snippets rendered inline. With isForDisplay=true, variables and snippets resolve into the content body. You get the rendered version, but you lose the reuse structure. With isForDisplay=false, you get raw tokens that will not render in Confluence. There is no option that preserves both fidelity and reuse.

  • Confluence page title uniqueness. Within a single Space, all page titles must be unique. Duplicate "Overview" or "Introduction" pages from different Document360 categories will collide.

  • Right-to-left (RTL) content. Document360 supports per-article RTL settings. Confluence handles RTL via language settings, not per-page toggles. RTL articles may need manual styling adjustments post-migration.

  • 64 KB page body limit. Very long Document360 articles with base64-encoded inline images can exceed this limit on the Confluence API. Convert base64 images to attachments before pushing the page body.

  • Category pages with content. Document360 categories can have their own body content. In Confluence, the equivalent parent pages must also have body content set — do not skip category descriptions or you will have blank container pages.

  • HTML import degradation. If using Confluence's native HTML importer, code blocks become plain text, iframe elements are unsupported, equations downgrade to plain text, and embedded videos become hyperlinks. (support.atlassian.com)

  • Metadata gaps. Document360 exposes workflow status, custom fields, translation status, and public/private visibility via API. Confluence can store some of these as page properties, labels, or restrictions, but it requires an explicit mapping plan. Nothing carries over automatically. (apidocs.document360.com)

Testing Plan: Structured Pilot Migration

Do not migrate your entire knowledge base on the first attempt. Run a structured pilot to validate your migration pipeline before committing to a full run.

Pilot scope

  • Sample size: Migrate at least 10% of your total articles, with a minimum of 20 pages.
  • Stratified selection: Include articles from each editor type (Markdown, WYSIWYG, Advanced WYSIWYG), each depth level of your category tree, and each language if multilingual.
  • Prioritize hard cases: Include at least 2–3 pages with each of these: complex tables, code blocks with multiple languages, inline images, internal cross-links, callout boxes, and duplicate titles.

Acceptance criteria

Check Pass Condition
Page count Pilot source count = pilot Confluence page count
Attachment count Per-page attachment count matches source media references
Internal links Zero broken internal links (run link checker)
Code blocks Syntax highlighting renders; content matches source
Images All inline images render; no broken-image icons
Hierarchy Parent-child relationships match source category structure
Labels Tags from source appear as labels on correct pages
Title collisions All duplicate titles resolved per renaming rules

Sign-off process

  1. Run the pilot migration into a staging space.
  2. Have a technical reviewer walk through the acceptance criteria checklist.
  3. Have a content owner review 5–10 pages for visual and content accuracy.
  4. Document any issues found and fix the migration pipeline before the full run.
  5. Re-run the pilot if pipeline changes were significant.

Only proceed to the full migration after the pilot passes all acceptance criteria.

Sample Timeline and What Affects Duration

A typical Document360 to Confluence migration takes between 1 to 4 weeks, depending on complexity.

  • Small (<200 articles, single language): 1–2 weeks. Mostly mapping and QA.
  • Medium (200–1,000 articles, mixed editors): 2–3 weeks. Requires custom parser adjustments for edge cases like complex tables or nested macros.
  • Large/Complex (1,000+ articles, multilingual, heavy media): 3–4 weeks. Rate limits dictate the transfer speed, and link rewriting requires multiple passes.

Factors that extend the timeline: Heavy use of Document360 variables/snippets (which must be expanded), extensive multilingual content, and strict API rate limits on your Document360 tier.

Phase Estimated Effort
Source audit and planning 2–4 hours
Extraction scripting 4–8 hours
Format converter (Markdown + HTML → Storage Format) 16–40 hours (the bulk of engineering work)
Attachment pipeline 4–8 hours
Link rewriting (second pass) 4–8 hours
Pilot migration and validation 4–8 hours
Full migration run 2–8 hours (dependent on volume and rate limits)
Post-migration QA and cleanup 4–8 hours
Total (DIY) 40–92 hours of engineering time

These estimates assume a single engineer familiar with both APIs. Teams new to Confluence's Storage Format should budget toward the higher end.

DIY Scripts vs. Marketplace Apps vs. ClonePartner

DIY API scripts

Best for: Engineering teams with Python/Node experience, fewer than 200 articles, and minimal inline media.

Hidden cost: The Markdown/HTML-to-Storage-Format converter is the real time sink. Expect 2–4 weeks of engineering time for a reliable parser that handles tables, code blocks, images, and nested lists. Budget additional time for the link-rewriting second pass and the attachment pipeline. In practice, you are building a parser, an uploader, a retry engine, a mapper, and a QA harness.

Risk: Formatting bugs that are invisible until readers report them. A paragraph that renders fine in Document360 might silently drop a nested list in Confluence because the Storage Format XML was not properly closed.

Marketplace apps

Best for: Small knowledge bases (under 50 articles) with simple formatting and no inline images.

Atlassian's own import documentation points to Marketplace apps for Markdown, HTML, and related formats. These tools are generic import helpers, not Document360-aware migration engines. (support.atlassian.com) They expect clean Markdown files, but Document360's Markdown often includes HTML fragments — especially for tables, callouts, and embedded content — which marketplace importers typically pass through as raw HTML rather than converting to Storage Format. They also do not handle the category hierarchy, cross-article link rewriting, or the attachment upload workflow.

ClonePartner managed migration

Best for: Knowledge bases with 100+ articles, mixed editor types (Markdown and WYSIWYG), heavy inline media, cross-article linking, or strict cutover deadlines.

Our migration engine handles the full pipeline: Document360 API extraction → format conversion (both Markdown and HTML to Storage Format) → attachment upload → internal link rewriting → validation. We manage both Document360's token-based rate limits and Confluence's API constraints to ensure zero dropped records. For a look at how we structure migration work, see How We Run Migrations at ClonePartner.

Our Migration Guarantees:

  • Zero Downtime: Your Document360 instance remains live and fully accessible during the migration. We sync the final delta right before cutover.
  • Full Validation Report: We provide a programmatic audit comparing source articles, attachment counts, and internal links against the Confluence destination.
  • No Data Left Behind: We map and migrate metadata, categories, and inline media accurately.

Frequently Asked Questions

How much downtime is required? Zero. Migrating Document360 to Confluence is a non-destructive read operation on the source side. Your existing documentation remains live until you update your DNS or internal links to point to Confluence.

How do you validate the migration? We run automated validation scripts that compare the total article count, attachment count per page, and link integrity between Document360 and Confluence. We also spot-check complex formatting like tables and code blocks.

How long does the migration take? Most migrations complete in 2 to 4 weeks. The exact timeline depends on your article count, media volume, and Document360 API rate limits.

What happens if the migration fails partway through? If you migrate into a staging space (which we recommend), you can delete the space and re-run from scratch. Your migration script should log every created page ID so you can roll back selectively if needed. The source Document360 instance is never modified during migration.

Does this work for Confluence Data Center, or only Cloud? The extraction and transformation steps are the same. The loading step differs — Data Center supports XML site imports and uses different authentication methods. The Storage Format itself is compatible across Cloud and Data Center.

Making the Right Call

Migrating from Document360 to Confluence is a format-conversion problem wrapped in a rate-limit-management problem. Document360's content is usually clean and well-structured. The challenge is getting that content into Confluence's proprietary format without losing formatting, breaking links, or orphaning images.

For small, text-heavy knowledge bases with under 50 articles and no inline media, a manual or semi-automated approach works. The Confluence HTML importer is a reasonable starting point if your content is already HTML.

For anything larger — mixed Markdown and WYSIWYG articles, heavy cross-linking, embedded images, multilingual content, or a strict cutover window — the engineering cost of building a reliable DIY converter usually exceeds the cost of hiring a team that has already solved this problem.

Whatever path you choose: prove title mapping, hierarchy, attachment fidelity, link rewriting, and metadata carryover in a pilot before you move the full tree. A migration that technically completes but leaves weeks of cleanup is not a successful migration.

Frequently Asked Questions

How much downtime is required?
Zero. Migrating Document360 to Confluence is a non-destructive read operation on the source side. Your existing documentation remains live until you update your DNS or internal links to point to Confluence.
How do you validate the migration?
We run automated validation scripts that compare the total article count, attachment count per page, and link integrity between Document360 and Confluence. We also spot-check complex formatting like tables and code blocks.
How long does the migration take?
Most migrations complete in 2 to 4 weeks. The exact timeline depends on your article count, media volume, and Document360 API rate limits.
What happens if the migration fails partway through?
If you migrate into a staging space (which we recommend), you can delete the space and re-run from scratch. Your migration script should log every created page ID so you can roll back selectively if needed. The source Document360 instance is never modified during migration.
Does this work for Confluence Data Center, or only Cloud?
The extraction and transformation steps are the same. The loading step differs — Data Center supports XML site imports and uses different authentication methods. The Storage Format itself is compatible across Cloud and Data Center.

More from our Blog