This blog used to run on WordPress. It now runs on Ghost, and I migrated it almost entirely through APIs — no clicking through import wizards. Here's how, and the sharp edges.
Exporting from WordPress
The cleanest path is the official @tryghost/migrate tool, which reads the WordPress REST API and produces a Ghost-importable bundle — posts, pages, tags, authors, and downloaded images:
migrate wp-api --url https://example.com --pages true
First gotcha: the tool needs Node 22+ (it uses the built-in node:sqlite module). Node 20 throws ERR_UNKNOWN_BUILTIN_MODULE.
Importing into Ghost
Second gotcha: don't feed the zip to Ghost's importer — extract the ghost-import.json and POST that to /ghost/api/admin/db/. The zip silently imports nothing. Images get copied into Ghost's content folder separately.
The 2FA wall
Ghost 5 emails a verification code on admin sign-in. With no SMTP configured yet, the session endpoint just returns 500. If you're automating against a fresh install, disable staffDeviceVerification until mail is wired up.
The rest — editing posts and pages — is all ?source=html on the Admin API, which converts your HTML into Ghost's native format. Past the gotchas, Ghost is a genuinely pleasant thing to script against.




