Skip to content

Bulk + Export/Import API

Sweep-actions across many Stories, plus full Space backup/restore.

Bulk story actions

http
POST /v1/spaces/{slug}/stories/bulk

Body:

json
{
  "action": "publish",
  "uuids": ["abc-...", "def-...", "..."],
  "options": { "publish_at": "2026-06-01T08:00:00Z" }
}

Supported action values:

actionoptionsEffect
publishpublish_at?Publish each story; with publish_at schedules instead of immediate
unpublishFlip status to draft
archiveSoft-delete (recoverable via restore)
restoreUndo archive
transitionto_stage (required)Workflow transition (RBAC + approval rules still apply)
deleteconfirm: "yes-permanently"Hard delete; requires admin role

Response: 200 { processed, failed: [{ uuid, error }] }. Partial failures are recorded — the rest still process.

Export

http
GET /v1/spaces/{slug}/export

Streams a .tar.gz containing:

  • stories.ndjson — one Story per line, all versions
  • blueprints.ndjson — component blueprints
  • locales.ndjson — Locale rows
  • audience-segments.ndjson — segments + rules
  • assets/ — original files (only when ?with_assets=1)
  • manifest.json — schema version + counts

Auth: auth:sanctum + space.scope middleware. Rate-limited throttle:5,60 (5 per hour) — the operation is expensive.

Import

http
POST /v1/spaces/{slug}/import
Content-Type: multipart/form-data

Field: bundle (the .tar.gz from export).

Modes (query param ?mode=):

modeBehaviour
dry-run (default)Validate, return diff, write nothing
mergeInsert new, update existing (matched by UUID)
replaceWipe target Space first, then import — destructive

Response includes a per-entity counts dict plus any UUID conflicts.

replace mode

replace deletes everything in the target Space (stories, blueprints, locales, segments) before import. Confirm twice in the admin SPA before clicking the button. CLI: peacock import bundle.tgz --mode replace --i-have-a-backup.

See also