Skip to main content
Import your Notion workspace into Moxn using the @moxn/kb-migrate CLI. It extracts pages, converts blocks into sections, downloads images, and recreates Notion databases as KB databases with tag-backed columns.
Prefer a UI? The same import is available as the in-app Notion integration — connect once in Settings > Integrations and Moxn runs the job for you. Both routes use the same engine; pick the CLI if you want scripted runs, CI integration, or fine-grained flag control.
If you have @moxn/context-cli installed, you can run context import-notion instead of npx @moxn/kb-migrate notion.

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.
  1. Go to notion.so/my-integrations and click New integration
  2. Name it (e.g. “Moxn Importer”), select your workspace, and click Submit
  3. Copy the Internal Integration Secret — this is your NOTION_TOKEN
  4. In Notion, open the top-level page you want to import
  5. 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

  1. Open the Moxn web app and go to Settings > API Keys
  2. Create a new key with read/write scope
  3. Copy the key — this is your MOXN_API_KEY

Step 3: Run the Import

That’s it. The tool discovers all pages in your workspace, converts them to KB documents, and uploads them.
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:
The --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/done and /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
Other property types (text, number, date, etc.) are not mapped to columns — they appear as text content within the page body.

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=team sets --default-permission=read
  • --visibility=private sets --default-permission=none
See Permissions for details on how the permission model works.

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

Pass your token via --token or set the environment variable:
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.
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.
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.
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.
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