← All playbooks
CMS migration

Payload → WordPress

Read Payload collections with the Local API and create WordPress posts through the REST API. Blocks, access rules, and uploads need a map. There is no official Payload-to-WXR button.

Typical timeline1 to 2 weeksA few days of script and theme work active work
Statusneeds review
Source profilePayload Local API and query docs reviewed 2026-11-06
Destination profileWordPress Tools Export and REST posts reference reviewed 2026-11-06
Documentation date
Review window
Evidence4 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

Payload

Reasons to stay
  • Open-source collections, blocks, and a Local API keep the content model in code you can host yourself
  • Editors get a purpose-built publishing workflow instead of raw files
Reasons to leave
  • There is no one-click importer, so schema, rich text, and media are a scripted project
  • Themes, extensions, and content models add maintenance and portability constraints
New platform

WordPress

What gets better
  • Unmatched ecosystem breadth and content ownership support almost any publishing model
  • Editors get a purpose-built publishing workflow instead of raw files
What gets worse
  • Plugin, hosting, security, and performance maintenance accumulate over time
  • Themes, extensions, and content models add maintenance and portability constraints
Best of the move

WordPress: Unmatched ecosystem breadth and content ownership support almost any publishing model. This removes a major source-side concern: There is no one-click importer, so schema, rich text, and media are a scripted project.

Worst of the move

What you lose: Open-source collections, blocks, and a Local API keep the content model in code you can host yourself. What you inherit: Plugin, hosting, security, and performance maintenance accumulate over time.

Jump to a section
01At a glance

Know the shape of the move.

Transfer outcome11 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 5, Manual rebuild: 4, Not transferred: 2.
Clean0
Partial5
Manual4
Lost2
Mapping route8 of 9 fields have a destination path

This timeline assumes

  • You can run a script inside the Payload app, where the Local API can read collections. find is paginated. Pass pagination false when you need every document and you accept the cost.
  • WordPress is a fresh site with an application password or a user who can create posts, media, and terms.
  • The site already documents Payload → Strapi, and WordPress → Payload in the other direction.
  • Gutenberg or the block editor will receive HTML or blocks you generate. Payload blocks do not become PHP blocks.
  • Editors stop publishing in Payload during the final copy.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
CollectionsmanualcriticalA Payload collection is code. WordPress will not read your config. Posts and pages are the usual targets. Other collections become custom post types only if you register them.Decide which collections become posts, pages, or a custom type. Skip the rest in writing.
Documentspartialcriticalpayload.find returns docs plus totalDocs. You create WordPress posts from that list. Store the Payload id in post meta so a second run updates instead of duplicating.Page through results or disable pagination on purpose. Upsert on the stored id.
Blocks and LexicalpartialcriticalLexical JSON and blocks are not Gutenberg. You render them to HTML or to block markup in the script.Convert one document per block type first. Keep the raw Payload JSON.
UploadspartialcriticalUpload collections point at files on disk or at an adapter such as S3. WordPress needs those files in the media library.Upload each file with the media endpoint and rewrite URLs in the post body.
RelationshipsmanualhighA relationship is a Payload id. WordPress wants a term, a parent, or meta. The id will not match.Create terms and posts first. Fill relationships after both sides have ids.
LocalizationmanualhighLocalized fields are not WordPress languages. A multilingual plugin has its own model.Import the default locale first. Add other locales only if the plugin is installed and mapped.
Access controllosthighPayload access functions are not WordPress roles. Users do not keep sessions.Create the editors you need and send new passwords.
GlobalsmanualmediumHeader and footer globals are single documents. WordPress menus are a different screen.Rebuild menus by hand from the global.
Versions and draftspartialmediumPayload versions are not WordPress revisions unless you create each one. Most moves only take the latest published document.Import published documents. Leave draft history in the Payload backup.
Hooks and custom endpointslosthighHooks that send mail, resize images, or sync a store do not run inside WordPress.List hooks that have side effects and replace the ones production needs.
Public URLspartialcriticalSlugs can match. Anything the frontend built from a route that is not the slug will 404.Crawl the live URLs. Redirect what you cannot recreate.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
Posts collectionWordPress poststransformREST POST /wp/v2/posts. Save the Payload id in meta.
Pages collectionWordPress pagestransformSame idea, pages endpoint.
Lexical or blockspost contenttransformRender to HTML or block markup.
UploadMedia librarytransformUpload the file, then replace URLs.
Category relationshipCategory termtransformCreate terms first.
SlugSlugautomaticKeep it when the URL should not change.
UserWordPress usermanualNew password. Map author ids after users exist.
Global navMenumanualRebuild it.
Access functionsNo destinationunsupportedSet roles in WordPress.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Keep a database dump and an upload archive before WordPress becomes the editor.

  1. Dump the Payload database.
  2. Copy the upload directory or the object-storage bucket.
  3. Record totalDocs per collection.
  4. Export WordPress once it has a baseline, using Tools, Export, so you can see what the script added.
  5. Store checksums.

Proof to capture: Dump checksum, upload count, and per-collection totals.

Transformation · payload.find

Read every document

Get a complete set despite pagination.

  1. Call find per collection.
  2. Either loop pages until you have totalDocs, or set pagination to false and a limit you can afford.
  3. Write a JSON line per document to a file you can rerun.
  4. Do not read drafts unless you mean to publish them.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · WordPress REST API

Create WordPress posts and media

Land content where editors already know how to work.

  1. Upload media first. Keep a map of Payload file id to WordPress attachment id.
  2. Create categories and users.
  3. Create posts and pages with the Payload id in meta. Render body HTML with rewritten image URLs.
  4. Second pass for anything that points at another post.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Export

Pagination hides documents

criticallikely likelihood

find defaults to a page of 10.

Consequence
You migrate a sample and call it the site.
Mitigation
Compare totalDocs with the number of WordPress posts you created.

Stop if: The counts differ and you have no exception list.

Content

HTML drops a block

highlikely likelihood

A block you do not render becomes nothing.

Consequence
Pages lose sections.
Mitigation
Convert one of each block before the full run.

Stop if: A sampled page is missing a section.

Cutover

Both admins stay writable

highpossible likelihood

Editors will keep using Payload if you do not say it is frozen.

Consequence
The last edits exist in only one system.
Mitigation
Freeze Payload, copy the delta, then send editors to WordPress.

Stop if: A document changed in Payload after the freeze and is not in WordPress.

06Precise timeline

Do the work in this order.

Estimate forOne Payload app, posts and pages, WordPress REST import
Total elapsed1 to 2 weeks
Active workA few days of script and theme work
BufferLocalization and odd blocks add a pass.
01
Day 1Count collections and blocks1 day
02
Day 2Prepare WordPress1 day
03
Days 3 to 5Import media and documents3 days
04
Day 6Compare URLs1 day
05
Day 7Freeze Payload and switch1 day
  1. Day 1 · inventory

    Count collections and blocks

    3 hours active1 day elapsedNone waiting
    • Record totalDocs.
    • List blocks and upload collections.
    • Dump the database.
    Stop / go checkpoint

    Is the scope a content move?

    Go when: You know which collections become posts or pages.

    Stop when: A collection is really the product catalog and nobody owns that decision.

  2. Day 2 · wordpress

    Prepare WordPress

    3 hours active1 day elapsedNone waiting
    • Install WordPress and the theme you will keep.
    • Create an application password.
    • Register custom post types you still need.

    Depends on: inventory

    Stop / go checkpoint

    Can the API create a post?

    Go when: A hand-made test post and a test image exist.

    Stop when: Auth or permalinks are wrong.

  3. Days 3 to 5 · import

    Import media and documents

    1 to 2 days active3 days elapsedUploads waiting
    • Upload files.
    • Create terms, users, posts, and pages.
    • Rewrite image URLs.

    Depends on: wordpress

    Stop / go checkpoint

    Do counts match?

    Go when: WordPress counts match totalDocs, with exceptions listed.

    Stop when: The gap is unexplained.

  4. Day 6 · preview

    Compare URLs

    4 hours active1 day elapsedNone waiting
    • Request the important URLs.
    • Check one page per block type.
    • Have an editor edit a post.

    Depends on: import

    Stop / go checkpoint

    Can editors move?

    Go when: The URL sample passes and an editor saved a post.

    Stop when: A block or a menu is missing.

  5. Day 7 · cutover

    Freeze Payload and switch

    2 hours active1 day elapsedDelta copy waiting
    • Stop Payload publishes.
    • Copy the delta.
    • Point the site at WordPress.

    Depends on: preview

    Stop / go checkpoint

    Stay on WordPress?

    Go when: The delta is in and the sample still passes.

    Stop when: Payload changed after the freeze.

07The point of change

Cut over with a way back.

Go live

Cutover

Make WordPress the editor and the public site, with Payload frozen.

Recommended window: After the URL sample, with the person who runs the script still online.

  1. Tell editors Payload is read-only. Record the time.
  2. Find documents changed after that time and create or update them in WordPress.
  3. Switch the public host.
  4. Leave Payload running for the rollback window.
  5. Send editors their WordPress logins.

Proof to capture: Freeze time, count table, and the URL sample.

Return to safety

Rollback

Point the site back at Payload if WordPress content is incomplete.

Deadline: While Payload is still deployed and the database dump is intact.

  1. Point the host back at the Payload frontend.
  2. Do not drop the WordPress database. You may need the delta.
  3. If editors wrote in WordPress, copy those posts back before they return to Payload.
  4. Re-open Payload publishing.
  5. List the URLs that failed.

Proof to capture: Payload serves the public host and WordPress-only edits are listed.

Rollback immediately when
  • Counts do not match and the exceptions are incomplete.
  • A sampled block is blank.
  • Media URLs 404.
  • A document changed in Payload after the freeze.
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
CNT-01BlockingtotalDocs versus WordPressCompare each collection you intended to move.Counts match or the exception file names every skip.The table.
PAG-01BlockingPaginationConfirm the script logged totalDocs and the number of rows it wrote.Those numbers match.The script log.
BLK-01BlockingOne page per blockCompare rendered HTML with the Payload admin.The sections you care about are present.The page list.
MED-01BlockingImage URLsSearch post content for the old asset host.Sampled posts point at the WordPress uploads directory.The search.
URL-01BlockingSlug sampleRequest the live paths.Important URLs return the right post.Status codes.
REL-01BlockingCategoriesOpen posts that had relationships.Terms match.Two example posts.
EDT-01BlockingA login worksHave an editor edit and update a post.The update saves.The post id.
FRZ-01BlockingFreezeCompare Payload updatedAt with the freeze time.Later edits are in WordPress.The timestamp check.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: WordPress has been the public site for a week and editors have published there.

  1. Keep the Payload dump and the upload archive.
  2. Revoke the application password if you do not need another delta.
  3. Leave Payload read-only until the retention date.
  4. Remove WordPress users created only for the script.
  5. Set the next review date.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. Payload: Local APIAccessed 2026-11-06
  2. Payload: queries and paginationAccessed 2026-11-06
  3. WordPress: Tools Export screenAccessed 2026-11-06
  4. WordPress REST API: postsAccessed 2026-11-06