@moxn/kb-migrate CLI. It extracts pages, converts blocks into sections, downloads images, and recreates Notion databases as KB databases with tag-backed columns.
Prerequisites
- Node.js 18+
- A Notion integration token with access to the pages you want to import
- A Moxn API key with read and write permissions (create one at Settings > API Keys in the web app)
Step 1: Create a Notion Integration
Moxn reads your Notion content through a Notion integration. You need to create one and grant it access to your workspace.- Go to notion.so/my-integrations and click New integration
- Name it (e.g. “Moxn Importer”), select your workspace, and click Submit
- Copy the Internal Integration Secret — this is your
NOTION_TOKEN - In Notion, open the top-level page you want to import
- Click the … menu in the top right, then Connections > Connect to and select your integration
The integration can only see pages it has been explicitly connected to. If you want to import your entire workspace, connect the integration at the top-level page and it will inherit access to all child pages.
Step 2: Get Your Moxn API Key
- Open the Moxn web app and go to Settings > API Keys
- Create a new key with read/write scope
- Copy the key — this is your
MOXN_API_KEY
Step 3: Run the Import
You can set environment variables instead of passing flags every time:
Preview First with Dry Run
See what would be imported without making changes:Import a Subtree
Import only a specific page and its children instead of the entire workspace:--root-page-id is the ID from the Notion page URL (the 32-character hex string after the page title).
Choose a Base Path
By default, documents are created under/imported-from-notion. Change this with --base-path:
How It Works
The migration runs in two passes:1. Discover
The tool searches your Notion workspace to find all pages and databases. It builds a tree of parent-child relationships and computes KB paths from page titles.2. Extract
For each page, the tool fetches all blocks and converts them to Moxn KB sections:
Content before the first H2 heading goes into an “Introduction” section.
3. Upload
Each extracted document is created via the Moxn API. The tool handles conflicts based on the--on-conflict option and continues processing if individual pages fail.
4. Databases
After all pages are imported, the tool creates KB databases from Notion databases:- Select and Multi-select properties become KB database columns
- Each option becomes a tag (e.g. a “Status” select with options “Done” and “In Progress” creates tags at
/imported/db-name/status/doneand/imported/db-name/status/in-progress) - Database entries (Notion pages within a database) are linked to the KB database
- Tag values from Notion properties are assigned to the corresponding documents
Document Path Mapping
The tool creates KB paths from the Notion page hierarchy:
Page titles are slugified: lowercased, spaces become hyphens, special characters removed.
CLI Options
Setting Permissions
Control who can see imported documents:
The
--visibility flag is a shorthand:
--visibility=teamsets--default-permission=read--visibility=privatesets--default-permission=none
Handling Conflicts
When you re-run the import and documents already exist at the target paths:--on-conflict=skip (default) — existing documents are left untouched:
--on-conflict=update — existing documents are replaced with the latest Notion content:
JSON Output
Use--json for structured output in CI or scripts:
Examples
Import entire workspace
Import a single team’s pages
Re-sync after Notion updates
Import with restricted AI access
Limitations
Troubleshooting
Error: Notion token required
Error: Notion token required
Pass your token via
--token or set the environment variable:Pages are missing from the import
Pages are missing from the import
The Notion integration can only access pages it’s been connected to. In Notion, open the parent page, click … > Connections > Connect to and select your integration. Child pages inherit access from their parent.
Images aren't showing up
Images aren't showing up
Notion-hosted images are downloaded and re-uploaded to Moxn storage during import. If the download fails (e.g. expired URL), the image is skipped with a warning. Re-running the import with
--on-conflict=update will retry failed images.External image URLs are kept as-is and must be publicly accessible.Database columns are missing
Database columns are missing
Only Select and Multi-select Notion properties are imported as KB database columns. Other property types (text, number, date, formula, relation, etc.) are rendered as text in the page body instead.
Import is slow
Import is slow
The Notion API has rate limits (~3 requests/second). For a workspace with 100+ pages, expect the import to take a few minutes. The tool shows progress as it goes.Use
--root-page-id to import a smaller subtree if you don’t need the entire workspace.Some pages failed but others succeeded
Some pages failed but others succeeded
The tool continues processing remaining pages when one fails. Check the summary output for failed pages and their error messages. Re-run with
--on-conflict=skip to retry only the failed ones (successfully created pages will be skipped).Next Steps
Concepts
Learn about documents, branches, and permissions
Connect AI Assistants
Set up MCP access so AI can use your imported docs