Coda to Confluence Migration: Methods, API Limits & Data Mapping
No native Coda to Confluence importer exists. Learn every migration method, hard API limits on both sides, and how to map Coda's relational tables to Confluence pages.
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 migration path from Coda to Confluence. No one-click importer, no Coda option in Confluence's import menu, no Atlassian-built migration wizard. There is not a direct Coda to Confluence importer. Coda builds a Confluence importer into its own product for the reverse direction, but moving to Confluence from Coda requires manual work, custom scripts, or a migration partner.
This guide covers the real methods for moving Coda workspaces into Confluence, the hard API constraints on both sides, and the data-mapping decisions that determine whether your migration succeeds or silently drops content.
Scope: This guide covers Confluence Cloud exclusively. Confluence Data Center uses different REST API endpoints, has different attachment and rate limit behaviors, and does not support the v2 page API referenced throughout. If you are migrating to Data Center, verify every endpoint and constraint against the Data Center REST API documentation.
| Method | Fidelity | Tables | Attachments | Automation | Best For |
|---|---|---|---|---|---|
| Manual Export → Import | Low–Medium | Flat CSV only | Manual re-upload | ❌ | Small workspaces (<50 pages) |
| Coda+ for Confluence (Embed) | N/A (not a migration) | Iframe only | ❌ | ❌ | Temporary coexistence |
| API-Driven Scripts | High | ✅ (as Confluence tables/macros) | ✅ (separate upload) | ✅ | Full workspace migrations |
| iPaaS (Zapier, Make, n8n) | Medium | Partial (row-by-row) | ❌ | ✅ | Ongoing sync, small data sets |
| ClonePartner Managed Migration | Highest | ✅ | ✅ | ✅ | Complex workspaces, zero downtime |
For teams evaluating the reverse direction, see our Confluence to Coda Migration guide.
Why Coda to Confluence Is Harder Than You Expect
Coda and Confluence solve fundamentally different problems, and their data models reflect that.
Coda is a document-database hybrid. A single Coda doc can contain pages of rich text and relational tables with formulas, lookups, cross-table references, buttons, and automations. Docs are the atomic unit of Coda. They house everything about a project — structured and unstructured — in one place.
Confluence is a wiki. Its atomic unit is a page — a block of content stored in Atlassian's XHTML-based storage format, organized in a hierarchical space → page → child-page tree. Confluence pages can contain static tables and macros, but they have no concept of relational lookups, formula columns, or cross-table references.
When you migrate, the dynamic elements break:
- Coda tables with formula columns lose all computed values. Confluence tables are static HTML; there is no formula engine.
- Cross-doc references and lookups break entirely. There is no equivalent concept in Confluence.
- Linked tables displayed across multiple Coda pages export as disconnected, static tables.
- Coda automations and buttons have no Confluence counterpart unless you rebuild them as Jira workflows or third-party macros.
- Coda views (filtered, sorted, or grouped views of a table) are not separate objects in the Coda API — they are accessed as tables with their own IDs. A view returns only the rows and columns visible in that view, not the full underlying table. During migration, you must decide: export the canonical table (complete data) or export each view separately (preserving the team's working perspective). Most migrations should export the canonical table and recreate filtered views as Confluence saved searches or child-page structures.
- Page hierarchy maps reasonably well (Coda pages → Confluence child pages), but Coda's flat-page-within-a-doc model does not always map cleanly to Confluence's space model.
If the business value lives in Coda's relations, formulas, and interactive controls, Confluence is only a partial destination. You can preserve information, but not behavior — at least not without redesign.
If you are evaluating whether Confluence's page-tree model is the right fit — or if Notion might be a better landing zone for relational workflows — see our Coda to Notion Migration guide.
Method 1: Manual Export and Import
This is the brute-force approach. It works for small workspaces with mostly narrative content. It does not scale.
Exporting from Coda
Coda offers limited native export options:
- The easiest way to export all of your docs at once is from your account settings. Go to Account Settings and scroll down to the Advanced Settings section, click on Export My Data. This will generate multiple .txt and .csv files for all of your owned docs.
- Export options are only for docs you own. If you are an org admin in an Enterprise workspace, you have additional export options through the admin API.
- Individual tables can be downloaded as CSV via the table's options menu. Coda recommends showing hidden columns and removing filters first — otherwise the export is incomplete by design.
- The Coda API offers an asynchronous page export endpoint (
POST /docs/{docId}/pages/{pageId}/export) that can generate HTML or Markdown per page. The download link is temporary, so fetch the file as soon as the status returns complete. (coda.io)
The account-level Export My Data produces .txt and .csv files only — it is not a structured workspace export. Enterprise admins can use the Admin API to export docs as PDF, Plaintext, or HTML. (help.coda.io)
Importing into Confluence
Easily bring existing work over to Confluence from Word, Google Docs, or OneDrive documents. Decide which document type you want to import: Word document (.docx), Google Doc, or OneDrive.
Notice what is missing: no CSV, no HTML, no Markdown in the native importer. Single imported docs are capped at 5 MB excluding attachments. Bulk imports allow up to 30 files, 50 MB total, with each file staying under 10 MB. (support.atlassian.com)
Confluence Cloud's editor supports markdown on the fly, so text with markdown formatting that is pasted directly into the editor will be converted. But this is a manual, page-by-page paste — not a bulk import.
For Markdown or HTML file imports, you need a third-party Marketplace app like the Markdown Importer for Confluence or the All-in-one File Importer (Pandoc-based). It supports Markdown, HTML, Microsoft Word (docx), LaTex, ODT, reStructuredText, EPUB, Docbook, wiki markup etc.
Step-by-step: Manual migration
- Export each Coda page's content via the API page export endpoint (HTML or Markdown) or copy-paste into a Word document. Export tables separately as CSV.
- Convert CSV tables to Word tables or HTML
<table>elements. - Import the .docx files into Confluence via Create → More actions → Templates and import → Import → Word document.
- Re-upload attachments (images, PDFs) manually to each Confluence page.
- Rebuild the page hierarchy by dragging pages under parent pages in Confluence's sidebar.
- Fix internal links — any link pointing to a Coda page will still be a
coda.ioURL. Once the Coda workspace is deprecated, those links are dead.
What you lose: Formula columns, cross-table lookups, conditional formatting, buttons, automations, comments, version history, and @-mentions. The manual method preserves content text and static table data — nothing else.
This method is fine for policy pages, SOPs, meeting notes, and other content where the page is the product. It is a bad fit for workspaces built on row relations and formulas.
Method 2: The Embed Workaround (Coda+ for Confluence)
The Coda+ for Confluence app on the Atlassian Marketplace looks promising at first glance. Coda+ for Confluence is the best way to seamlessly integrate Coda into your Confluence content. But read the fine print.
This app does not migrate data. The Coda + app only embeds Coda documents manually. Apparently, there is not enough demand for sync or import/export features.
What it actually does: embed a Coda doc inside a Confluence page via an iframe. The data still lives in Coda. It is not indexed by Confluence search. It is not backed up with your Confluence space. If your Coda subscription lapses, the embeds go blank.
Use the embed when:
- You need a short bridge period while planning a real migration
- A team still actively edits in Coda
- Search and governance inside Confluence are secondary concerns
Do not use it when:
- You are decommissioning Coda
- You need native Confluence search and page-level permissions
- Legal or operational ownership must move with the content
This is a coexistence strategy, not a migration path.
Method 3: API-Driven Migration
This is the only method that can handle a full workspace migration with structural fidelity. It is also the most technically demanding.
The approach: read data from the Coda REST API (v1), transform it into Confluence's XHTML storage format, and write it to the Confluence REST API (v1 or v2).
Extraction: Coda API
The Coda API exposes a clean hierarchy: Docs → Pages → Tables → Columns → Rows. Authentication is via Bearer token generated from your Coda account settings.
Use immutable IDs, not display names. Coda's API docs explicitly warn that names are fragile and can change. Build your entire migration from doc IDs, page IDs, table IDs, column IDs, and row IDs. (coda.io)
Core endpoints for extraction:
# List all docs accessible to the token
GET https://coda.io/apis/v1/docs
# List pages within a doc
GET https://coda.io/apis/v1/docs/{docId}/pages
# Export a single page as HTML or Markdown (async)
POST https://coda.io/apis/v1/docs/{docId}/pages/{pageId}/export
# List tables within a doc
GET https://coda.io/apis/v1/docs/{docId}/tables
# List rows within a table (paginated)
GET https://coda.io/apis/v1/docs/{docId}/tables/{tableId}/rowsEndpoints supporting listing of resources have the following fields: items, nextPageLink, nextPageToken. The maximum page size may change at any time, and may be different for different endpoints. You should look for the presence of the nextPageToken on the response to see if there are more results available.
In practice, the List Rows endpoint typically returns up to 500 rows per page. You must implement pagination using pageToken — there is no way to get all rows in a single request for larger tables.
Use valueFormat=rich when you need to preserve links and rich text formatting in cells. It is slower to process but prevents silent data loss in important columns.
Snapshot reads, not live reads. Coda API reads come from a recent snapshot of the doc, not guaranteed live state. For final delta syncs near cutover, Coda supports the X-Coda-Doc-Version: latest header — this forces the API to fail rather than return a stale snapshot. Useful for QA, but expect transient 400s while the doc snapshot catches up. (coda.io)
Coda views
Coda views (filtered, sorted, or grouped presentations of a table) appear as entries in the GET /docs/{docId}/tables response — each view has its own table ID. When you list rows for a view ID, you get only the rows and columns that view exposes. This means your extraction script will encounter views alongside canonical tables. Tag each by checking the tableType field: "table" for canonical tables, "view" for views. In most migrations, you should extract the canonical table for completeness and skip duplicate view exports unless a specific view represents a distinct, business-critical perspective that warrants its own Confluence page or filtered child-page set.
Coda Pack data
Packs pull external data into Coda tables — CRM records, calendar events, GitHub issues, etc. Columns populated by Pack sync tables are readable through the Coda API just like any other column: you get the last-synced value. However, Pack sync metadata (sync frequency, connection credentials, sync status) is not exposed through the API. Once you migrate Pack-sourced data to Confluence, it becomes a frozen snapshot. If the upstream source matters post-migration, you will need a separate integration (e.g., a Jira-Confluence link or a direct API connection to the source system) to keep that data current in Confluence.
The Transformation Layer
The hard part is not the API calls — it is the transformation between Coda's data model and Confluence's storage format. Here is what a migration script must handle:
| Coda Object | Confluence Equivalent | Transformation Required |
|---|---|---|
| Page (canvas content) | Confluence page body (XHTML) | HTML sanitization, macro conversion |
| Table (with columns/rows) | Static <table> or Confluence table macro |
Flatten formulas to last-known values |
| Formula column | Static text column | Evaluate and freeze values |
| Lookup / Relation column | Plain text or cross-link | Resolve references, insert page links |
| Image attachment | Page attachment + <ac:image> tag |
Upload via attachment API, update references |
| @-mention | Confluence user mention macro | Map Coda user IDs → Atlassian account IDs |
| Button / Automation | Nothing (no equivalent) | Document in migration notes |
| View (filtered/sorted table) | Filtered child-page set or skip | Export canonical table; recreate view logic manually or via labels |
| Pack sync column | Static text column | Freeze last-synced value; plan separate integration if live data needed |
Be careful with volatile formulas like Today(), Now(), and User(). Coda's API docs note that time-based values may lag the live doc and user-based values may be blank or invalid through the API. Decide before migration whether these columns are worth preserving as frozen snapshots. (coda.io)
Sample transformation: HTML sanitization and formula freezing
The extraction and ingestion APIs are well-documented, but the transformation layer is where most scripts break. Below is a Python skeleton that handles two of the most common transformation tasks: sanitizing Coda HTML output for Confluence's XHTML-strict storage format and freezing formula column values.
import re
from html import escape
def sanitize_for_confluence(html_content: str) -> str:
"""
Sanitize HTML extracted from Coda for Confluence storage format.
Confluence requires XHTML-strict: all tags closed, special chars escaped,
no bare &, <, > in text nodes.
"""
# Escape unescaped ampersands not already part of an entity
html_content = re.sub(r'&(?!amp;|lt;|gt;|quot;|apos;|#)', '&', html_content)
# Self-close void elements (img, br, hr) for XHTML compliance
for tag in ['img', 'br', 'hr']:
html_content = re.sub(
rf'<({tag})([^>]*?)(?<!/)>',
rf'<\1\2 />',
html_content
)
return html_content
def freeze_formula_columns(rows: list, columns: list) -> list:
"""
Replace formula column values with their last-known computed values
as static strings. Marks volatile formulas (Today, Now, User) with
a warning prefix.
"""
volatile_patterns = ['Today()', 'Now()', 'User()']
formula_col_ids = {
col['id'] for col in columns
if col.get('calculated', False)
}
for row in rows:
for col_id in formula_col_ids:
if col_id in row.get('values', {}):
value = row['values'][col_id]
# Check if the column formula is volatile
col_def = next((c for c in columns if c['id'] == col_id), {})
formula = col_def.get('formula', '')
is_volatile = any(v in formula for v in volatile_patterns)
if is_volatile and (value is None or value == ''):
row['values'][col_id] = '[volatile formula — no value at export time]'
else:
# Freeze as escaped string for XHTML safety
row['values'][col_id] = escape(str(value)) if value else ''
return rowsThis is a skeleton, not a production-ready script. A real transformation pipeline also needs to handle: Coda's rich text cell format (valueFormat=rich returns objects, not strings), image reference rewriting (Coda CDN URLs → Confluence attachment references), @-mention mapping, and Confluence macro insertion for status badges or labels.
Ingestion: Confluence API
Confluence Cloud supports both v1 (/wiki/rest/api/content) and v2 (/wiki/api/v2/pages) REST APIs. For page creation, v2 is simpler — it uses spaceId instead of space keys.
For attachments, the current Cloud docs still document create/update in REST v1, while REST v2 attachment endpoints focus on list, get, and delete. In practice, most migration pipelines create pages via v2 and upload files through the v1 attachment endpoint. (developer.atlassian.com)
# Export a Coda page as Markdown (async)
curl -X POST "https://coda.io/apis/v1/docs/$DOC_ID/pages/$PAGE_ID/export" \
-H "Authorization: Bearer $CODA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"outputFormat":"markdown"}'
# Create a Confluence page (v2 API)
curl -X POST "https://your-site.atlassian.net/wiki/api/v2/pages" \
-H "Authorization: Bearer $ATLASSIAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"spaceId": "12345",
"status": "current",
"title": "Migrated from Coda: Project Tracker",
"parentId": "67890",
"body": {
"representation": "storage",
"value": "<h2>Project Tracker</h2><table><tr><th>Task</th><th>Status</th></tr>...</table>"
}
}'The body.value field expects Confluence storage format — an XHTML dialect that includes Atlassian-specific macros (<ac:structured-macro>, <ac:rich-text-body>, etc.). Standard HTML tags like <table>, <p>, <h2> work, but anything Coda-specific (formulas, buttons, conditional formatting) must be converted or dropped.
Your migration script must maintain a source-to-target ID registry — mapping every Coda page ID to its newly created Confluence page ID — so you can rewrite internal links after all target pages exist.
Rollback and Partial Failure Handling
API-driven migrations fail partway more often than they succeed on the first run. A 500-page migration hitting a malformed XHTML body at page 347, a rate-limit storm, or a Coda snapshot going stale mid-export are all common scenarios. Your script needs to handle this.
State tracking. Persist your source-to-target ID registry to disk (a JSON file or SQLite database, not just in-memory). After each successful page creation, write the mapping immediately. When the script fails, you have a record of what was already created in Confluence.
Idempotent writes. Before creating a page, check your registry for an existing target ID. If the page was already created in a prior run, update it instead of creating a duplicate. Confluence's v2 API supports PUT /wiki/api/v2/pages/{id} for updates.
Retry logic. On HTTP 429 (rate limited) or 5xx (server error), implement exponential backoff with jitter. Do not retry on 400 (bad request) — that means your payload is malformed and needs to be fixed, not retried.
Cleanup on abort. If you need to wipe a failed partial migration and start fresh, your registry tells you exactly which Confluence pages to delete. Without it, you are manually hunting through the Confluence space for orphaned pages.
Method 4: iPaaS Workflows (Zapier, Make, n8n)
Tools like Zapier, Make, and n8n offer pre-built connectors for both Coda and Confluence. A typical workflow: New Row in Coda table → Create Page in Confluence. This maps one Coda table row to one Confluence page.
Where iPaaS works:
- Ongoing sync of a single Coda table to Confluence pages (e.g., a knowledge base where each row = one article)
- Small data volumes where rate limits are not a concern
- Teams without engineering resources for custom scripts
Where iPaaS breaks:
- Migrating page content (canvas text, rich formatting) — Zapier's Coda trigger only fires on row changes, not page edits
- Large tables — Zapier has its own task limits, and Coda's trigger rate compounds with API rate limits
- Complex hierarchy — there is no native way to recreate Coda's page tree as a Confluence page tree in a single Zap
- Attachments — no iPaaS connector handles Coda attachment extraction and Confluence attachment upload natively
iPaaS is best for ongoing sync of structured data after an initial migration, not for the migration itself.
Critical API Limits and Technical Bottlenecks
This is where most DIY migration scripts fail. Both APIs have hard limits that are not always obvious from the docs.
Coda API Limits
The 125 MB wall. On all plan types, docs with a size of 125 MB or more will no longer be accessible via the Coda API. Note that 125 MB does not include file attachments. If your doc exceeds this threshold, the API will refuse requests entirely — no partial reads, no workaround. You must manually split the doc in Coda's UI before an API-based migration can proceed. Check doc sizes via GET /docs/{docId} — the docSize field reports current size.
Rate limits are strict and per-user across all docs:
Reading data: 100 requests per 6 seconds. Writing data (POST/PUT/PATCH): 10 requests per 6 seconds. Writing doc content data (POST/PUT/PATCH): 5 requests per 10 seconds. Listing docs: 4 requests per 6 seconds.
The limit for requests is 2 MB, but there is also a limit of 85 KB for any given row.
For robustness, all API scripts should check for HTTP 429 Too Many Requests errors and back off and retry the request.
At 100 read requests per 6 seconds with ~500 rows per page, extracting a table with 50,000 rows takes a minimum of ~100 paginated requests — roughly 60 seconds of pure API time assuming no 429s. In practice, with jitter and retries, expect 2–5 minutes per large table.
Temporary download links. Page export download URLs expire. If you queue thousands of async exports and wait too long to fetch the results, you create your own failure mode. Download each export immediately upon completion. (coda.io)
Confluence Cloud API Limits
Atlassian recently overhauled its rate-limiting model. Enforcement of the new points-based API rate limits and tiered quota rate limits for Jira and Confluence Cloud apps will begin on March 2, 2026.
Confluence Cloud uses a points-based model to measure API usage. Instead of simply counting requests, each API call consumes points based on the work it performs — such as the amount of data returned or the complexity of the operation.
Key constraints for migration scripts:
- Quota and burst rate limits are enforced independently. Burst limits are evaluated over short time windows (typically seconds) to prevent traffic spikes, while quota limits are evaluated hourly. Even if you remain within your hourly quota, a rapid surge of requests can trigger burst limiting.
- API token-based traffic is not affected by this change, and will continue to be governed by existing burst rate limits. This is important: if you authenticate with an API token (not an OAuth app), you are only subject to burst limits, not the new points-based quotas.
- It works fine for a "normally-sized" table but there seems to be a limit when the content starts getting big. Beyond roughly 64K, you may get a 400 Bad Request error. This is a practical limit on
body.storage.value— large Coda pages with massive tables will need to be split across multiple Confluence pages. - When the "body" expansion is specified, the limit is set to 50. If no expansions are specified, results are limited to 1000. And if other expansions besides "body" are specified, the limit is set to 200. This affects how you verify migrated content — querying pages with body expansion for validation caps results at 50 per request.
- The default attachment maximum size is 100 megabytes.
- Confluence's native document import caps a single file at 5 MB (excluding attachments), with bulk imports at 30 files and 50 MB total. (support.atlassian.com)
The 125 MB wall: If any single Coda doc exceeds 125 MB (excluding attachments), the Coda API will block all access to it. There is no "partial read" mode. You must manually split the doc in Coda's UI before an API-based migration can proceed. This affects a small percentage of docs, but if you are migrating a large knowledge base, audit doc sizes first.
Data Mapping: Coda Objects to Confluence Equivalents
The mapping decisions you make here determine the quality of your migration. There is no single right answer — it depends on how your team will use the content in Confluence.
Coda doc → Confluence space or page tree?
Confluence is structured as a traditional wiki, meaning within your workspace, you have giant "spaces" where all of your information lives in individual pages and subpages.
A Coda doc maps most naturally to a Confluence page tree under a parent page. If you have multiple Coda docs, you can either:
- Create one Confluence space per Coda doc (best for large, self-contained docs)
- Create one parent page per Coda doc within a shared space (best for smaller docs that belong to the same team)
Coda table → Confluence table or child pages?
This is the most impactful decision. You have two options:
Option A: Static Confluence table. Convert each Coda table to an HTML <table> in the Confluence page body. Fast to render, easy to scan, but limited to roughly 100–200 rows before the page becomes unusable. Good for reference tables and lookup data.
Option B: One child page per row. Create a Confluence page for each Coda row, with field values laid out as page content or page properties. Scales to any table size, supports Confluence search, but creates a large number of pages. Good for CRM records, project trackers, and any table where individual rows need their own context.
Formulas and computed columns
Coda formulas have no Confluence equivalent. Your options:
- Freeze values: Read the current computed value from the API and store it as static text. This is what most migrations do. It is accurate at the moment of migration but will not update.
- Drop the column: If the formula is ephemeral (e.g., "Days Since Last Update"), it may not be worth migrating.
- Replace with Jira fields: If the formula tracks status, priority, or dates, consider linking Confluence pages to Jira issues where those fields can be maintained dynamically.
Attachments and images
Coda stores attachments inline and via its own CDN. The API returns attachment URLs, but these are often temporary signed URLs. Your migration script must:
- Download the file from the Coda URL immediately.
- Upload it to the Confluence page as an attachment via
POST /wiki/rest/api/content/{pageId}/child/attachment. - Update the page body to reference the Confluence attachment using
<ac:image><ri:attachment ri:filename="image.png" /></ac:image>.
Skipping this step means broken images everywhere.
Edge Cases and Failure Modes
These trip up teams consistently:
- Coda buttons and automations — these do not exist in Confluence. Document them in a migration runbook so teams know what manual processes replace the automations.
- Cross-doc references — if Doc A references a table in Doc B, you need to decide whether to merge them into one Confluence space or use cross-space links. Cross-doc formulas that pull live data from another doc will resolve to their last-synced value at export time — verify these values during QA, as stale cross-doc references are a common source of silent data loss.
- Conditional formatting — Coda tables with color-coded rows based on conditions lose all visual context. Consider using Confluence status macros (
<ac:structured-macro ac:name="status">) as a partial replacement. - Page-level permissions — Coda's sharing model (doc-level) does not map to Confluence's page-level restrictions. Plan your permission model in Confluence before migration.
- Unicode and special characters — Confluence's storage format is XHTML-strict. Unescaped
&,<, or>in Coda content will cause 400 errors on the Confluence API. Your transformation layer must sanitize all content. - Duplicate page titles — Confluence requires unique page titles within a space. If your Coda doc has multiple pages with the same name (common in templates), the migration script must append unique suffixes.
- Volatile formulas —
Today(),Now(), andUser()may return lagging or blank values through the API. Decide before migration whether to freeze these or drop them. - Pack sync and Cross-doc data — any data pulled into Coda via Packs or Cross-Doc becomes a static snapshot in Confluence. Pack sync columns are readable through the API (you get the last-synced value), but sync metadata, connection credentials, and refresh schedules are not exposed. If the upstream source matters, plan a separate integration in Confluence (e.g., Jira links, direct API connectors, or Marketplace apps) rather than expecting Pack data to stay current.
- Coda views — views appear as separate table IDs in the API. If you export both the canonical table and its views without deduplication, you will create duplicate data in Confluence. Track which table IDs are views (check
tableType) and decide per view whether it warrants a separate Confluence page or should be skipped.
Pre-migration audit: Before writing any code, run a Coda API inventory. List all docs (GET /docs), count pages and tables per doc, check doc sizes, and identify any docs over 100 MB. This 30-minute exercise will save you days of debugging.
How ClonePartner Handles Coda to Confluence Migrations
We built our Coda → Confluence pipeline to handle the constraints above. Here is what that looks like in practice:
- 125 MB doc workaround: For oversized docs, we use a hybrid extraction approach — combining API reads (for docs under the limit) with structured bulk exports and HTML parsing (for docs above it) — so no data is left behind.
- Rate limit orchestration: Our scripts implement adaptive throttling with exponential backoff on both the Coda and Confluence sides, coordinating read and write quotas to maximize throughput without triggering 429s.
- Table-to-page intelligence: We work with your team to decide which tables become static Confluence tables and which become page trees with properties — based on row count, update frequency, and how the data is actually used.
- Attachment pipeline: Images and files are downloaded, checksummed, and re-uploaded to Confluence with correct references — no broken images, no missing PDFs.
- Link rewriting: We maintain a full source-to-target ID map, rewriting all internal Coda links to point at the correct Confluence pages before the final publish.
- Validation pass: After migration, we run an automated diff comparing Coda source data against Confluence pages — page count, table row count, attachment count — and flag any discrepancies before sign-off.
We have handled similar complexity in Notion-to-Confluence migrations, where the same block-based → wiki-based structural mismatch applies. Coda adds the extra challenge of relational tables, which we address with custom mapping logic per workspace.
Decide Your Landing Model Before You Write a Script
The common mistake is exporting everything first and deciding structure later. Do the opposite. Define which Coda data becomes native Confluence pages, which becomes static tables, which stays as attachments, and which should not move to Confluence at all — before you write a single line of migration code.
If you have fewer than 50 pages and no complex tables, the manual method works. Tedious but finite.
If you have structured data in Coda tables that needs to be searchable and maintained in Confluence, you need an API-driven approach — either DIY or managed.
If you have a large workspace with cross-references, formulas, and attachments, and you need the migration done in days rather than weeks, that is exactly what we do. The safe pattern is a pilot on one representative space, a full dry run, stakeholder QA, and only then a final delta sync. That is the difference between copying pages and migrating a knowledge system.
If Confluence is too rigid for a database-heavy workspace, compare your options with our Coda to Notion migration guide. If you are evaluating the reverse direction or building a coexistence plan, our Confluence to Coda guide is the counterpart.
Frequently Asked Questions
- Is there a native Coda to Confluence importer?
- No. Atlassian does not offer a direct importer for Coda. You must use manual exports (Word/CSV), iframe embeds via Coda+ for Confluence, custom API scripts, or a managed migration service.
- What are the Coda API rate limits for migration?
- Coda's API allows 100 read requests per 6 seconds, 10 write requests per 6 seconds, and 5 doc-content writes per 10 seconds. Docs over 125 MB (excluding attachments) are completely blocked from API access. All limits are per-user across all docs.
- Does the Coda+ for Confluence app migrate data?
- No. Coda+ for Confluence only embeds Coda documents in Confluence pages via iframes. The data remains in Coda, is not indexed by Confluence search, and will break if your Coda subscription expires. It is a coexistence tool, not a migration tool.
- How do I handle Coda formula columns in Confluence?
- Confluence has no formula engine. The standard approach is to freeze formula values — read the current computed value from the Coda API at migration time and store it as static text. Alternatively, replace dynamic fields with linked Jira issue fields where those values need to stay current.
- What Confluence API limits affect large migrations?
- Confluence Cloud enforces burst rate limits per-second and (starting March 2026 for OAuth/Forge/Connect apps) points-based hourly quotas. API token traffic uses burst limits only. Page body content over roughly 64 KB can trigger 400 errors, and queries with body expansion are capped at 50 results per request.

