Skip to content

Bulk import overview

Bulk import creates or updates many records at once from JSON files. Find it under Tools → Octa Editor → Import.

The same upload field also takes an image manifest from bulk media optimisation. The kind of file is recognised automatically, so you never have to pick an importer.

  1. Upload one or more .json files. One file is one document, a post or a term. File names don’t matter, and are only used in the preview.
  2. Dry-run preview. The importer resolves every file and shows, per file, exactly what will happen, such as CREATE, UPDATE → ID 123 with the keys it changes, or UNCHANGED → ID 123, plus all warnings. Counters above the table add up each group. Nothing is written yet.
  3. Confirm. Only now are the changes applied. Unchanged records are skipped, so their modification date stays as it was.
  4. Report. You get a per-file result of what was created, updated, left unchanged, skipped or failed.

You don’t need to order the files. The importer processes them in dependency order, terms first, then parent posts, then children. References within the batch are allowed. A parent in one file, a term in another, and a relation to a third all resolve against the same batch, matched by slug.

  • Mutual relations (A to B and back) are fine. Relations are wired up in a second pass after all records are saved.
  • Re-importing a package is safe. Records that already match are left alone, and children or relations in the package still attach to them.
  • The one unrecoverable error is a parent cycle, where A is B’s parent and B is A’s. It rejects the whole batch.
  • The same (parent, slug) in two files of one batch is a duplicate, and both are flagged.

The save runs in steps. The preview keeps the checked batch on the server, and pressing Save starts a series of short requests: each one writes records for up to about 20 seconds (less on a server with a tight time limit), remembers where it stopped and shows the progress. A fast server finishes in a step or two, a slow one in many, and neither hits its time limit, so one ZIP can carry the whole site.

Progress is stored after every record, and the record being written is marked first. If a request drops (a timeout, a lost connection, a fatal error in another plugin), the page retries and the save continues from where it stopped. A record the cut request had already created is finished as that same record, never created a second time. A file that stops the server twice in a row is reported as failed, and the rest of the import goes on. If the page gives up, the button turns into Continue saving. A save that outlives its page (a long import, a laptop that went to sleep) renews its security token on its own; if you were logged out, the page says so, and after you log in again in another tab, Continue saving picks up where it stopped. Only one window saves an import at a time, and a second one waits for it. Without JavaScript the same form saves everything in one request, in the same short steps, and a second press of Save shows the same report without saving anything again.

Until it is saved, the checked batch waits on the server in wp-content/uploads/octa-editor/, under a name nobody can guess. A batch left at the preview expires after a day, a finished one a few minutes after its report. The files begin with a line that stops PHP. On nginx, which ignores the folder’s .htaccess, the unguessable name is the main protection, so keep the folder out of public backups and syncs.

The top of the Guide tab shows what one import on this site can take: how many documents, how much JSON, how large an upload and how many loose files at once. The Export and Import tabs link to it. One import takes up to 1000 documents, and the JSON budget follows the PHP memory_limit, because the preview checks the whole batch at once.

PHP enforces two limits on the upload quietly, and the importer catches both.

  • Too many loose files (max_file_uploads, often 20). PHP drops the extra files. The Import tab warns as soon as you pick more and blocks the upload; pack the files into one .zip instead.
  • A request that is too large (post_max_size). PHP throws the whole request away. The importer explains that instead of quietly showing the form again.

A site larger than one import goes in several imports: taxonomies and parent pages first, then the records that point at them, because a link between records resolves only to what already exists on the site or in the same import. Re-running an import is safe, since records that already match are skipped.

The JSON budget covers the whole upload: several archives or loose files together cannot pass it, and a file that no longer fits is listed with the reason.

A proxy in front of PHP (for example an nginx client_max_body_size) can be stricter than PHP itself. Tell the plugin through the octa_editor_server_limits filter: its upload_max and post_max set the upload cap, and max_execution_time sets how long each save step runs.

Bulk import only creates and updates. It never deletes, and a trash status is rejected.

The surest way to get fields names right is to copy the shape of a record that already exists. Export whole types as a ZIP on the Export tab (see Export and roundtrip), or open a single record on the site and use Download JSON in the editor panel. Change the values, and you have a valid import file.

The Guide tab walks through the export, agent and import steps and carries the agent guide, which documents the exact rules an AI agent needs to produce valid files. Copy it to the clipboard or download it as plain text. The typical flow is to export the content, hand the files plus the guide to an agent, and import what it produces.

Next, see Preparing JSON files.