Documentation

Publishing and releases

Every content item has one mutable draft and, after its first publish, one published snapshot. Editing a draft never changes what the site serves, and publishing copies the draft's current values into the snapshot for the locales you name. Unpublishing removes locales from the snapshot without touching the draft. For the exact shape of both documents, see Content JSON.

Publishing per locale

Publish takes a list of locales:

bash
code
curl -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  "$API_URL/v1/orgs/$ORG_ID/content/$SPACE_ID/article/$CONTENT_ID/publish" \
  -d '{ "locales": ["en", "is"] }'

Publishing one locale never leaks another locale's unpublished edits. Blobify merges the requested locales into the previous snapshot and preserves the locales that were already live. Required fields are enforced for the locales you publish, and locales that are not configured on the organization are rejected. Models with no translatable fields skip the locale picker in the dashboard entirely and publish once.

Use /can-publish (or the canPublish MCP tool) to dry-run the publish-time validators, including uniqueness, before you commit. Unpublish uses the matching /unpublish route, and omitting locales unpublishes every locale that is currently live.

Scheduled publish and unpublish

A single entry can be scheduled for a future publish, a future unpublish, or both at once. A status notice can go live now and retire itself when maintenance ends.

bash
code
curl -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  "$API_URL/v1/orgs/$ORG_ID/content/$SPACE_ID/article/$CONTENT_ID/schedule-publish" \
  -d '{ "at": "2026-09-10T08:00:00Z", "locales": ["en"], "action": "publish" }'
  • Times are stored in UTC at minute precision and must be in the future. Always confirm the time zone you meant: an hours-off launch is the real hazard, not seconds.
  • action is publish (the default) or unpublish. Each entry can hold one pending schedule per action, so the two never collide, and re-posting the same action reschedules it.
  • locales is optional. For a publish it means every publishable locale. For an unpublish it is resolved when the schedule fires, so a locale an editor already took down by hand is skipped and no duplicate event is emitted.
  • A scheduled unpublish must land later than a pending scheduled publish for the same locale set.
  • Scheduling an entry that has no draft returns 404 rather than failing confusingly at fire time.
text
code
GET    /v1/orgs/{orgId}/content/{spaceId}/{model}/{contentId}/schedule-publish
DELETE /v1/orgs/{orgId}/content/{spaceId}/{model}/{contentId}/schedule-publish?action=unpublish
GET    /v1/orgs/{orgId}/content/{spaceId}/scheduled-publishes

GET on the entry route returns both records. DELETE cancels one action, defaulting to publish, and returns 404 when there is no record and 409 once the record is no longer cancellable. The space-wide route lists every schedule with its action, status, locales, and result.

A scheduled unpublish behaves exactly like a manual one, including what it does not do. It does not archive or delete the entry, it leaves the draft untouched, and it clears no editorial metadata. A locale that is already unpublished is a successful no-op.

Releases

A release is a named group of documents prepared together and published together, optionally at a scheduled time. Use one when a launch spans several pages and they must go live in the same minute.

  1. Create the release and choose its diverged-draft policy.
  2. Add documents. Adding copies each document's current draft into a working copy owned by the release. The draft is never touched by adding or removing.
  3. Edit the copies. Edits to a working copy are invisible to the site and independent of the draft, so the everyday draft can keep shipping in the meantime.
  4. Publish or schedule the release.

A document belongs to at most one release in an open state (open, scheduled, or publishing) at a time. Adding a document that another release already claims fails that item only, and names the release holding it.

At publish time, each member is published from its working copy, with per-item results: one failure never sinks the batch, and the release ends failed with the detail attached. Drafts are handled per member. A draft that has not moved since it was added is fast-forwarded, so draft, published, and release content all agree. A draft that has moved follows the release's onDivergedDraft policy, which the publish call can override:

  • flag (the default) publishes the working copy and keeps the draft's edits, so the entry then reads as changed since publish.
  • overwrite replaces the draft with the working copy first. The replaced edits stay recoverable in version history. Nothing is ever merged automatically.

The dashboard's release page shows members, per-item status, and which drafts have diverged, plus a field-level pick-a-side view for resolving a diverged member before the release ships.

Discarding is a two-step, like deleting content. Discarding an open or scheduled release deletes the working copies, frees the documents for other releases, and leaves the drafts alone. Discarding an already terminal release (published, failed, or discarded) removes the record for good. Published content is never affected either way, and a release that is mid-publish cannot be touched.

text
code
POST   /v1/orgs/{orgId}/releases/{spaceId}
GET    /v1/orgs/{orgId}/releases/{spaceId}
GET    /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}
DELETE /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}
POST   /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/items
DELETE /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/items/{model}/{contentId}
GET    /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/items/{model}/{contentId}/copy
POST   /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/items/{model}/{contentId}/copy
POST   /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/publish
POST   /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/schedule
DELETE /v1/orgs/{orgId}/releases/{spaceId}/{releaseId}/schedule

Every release route needs editor or higher, and an API key needs the content:publish grant. Release publish does not accept a locale list, so a key restricted to specific locales cannot publish a release. Use per-entry publish calls instead.

MCP tools

Single entries: publish, unpublish, bulkPublish, canPublish, schedulePublish, cancelScheduledPublish, listScheduledPublishes.

Releases: createRelease, listReleases, getRelease, addToRelease, removeFromRelease, getReleaseCopy, saveReleaseCopy, publishRelease, scheduleRelease, unscheduleRelease, discardRelease. Compare getReleaseCopy with getContent to see how a working copy and its draft have diverged. See MCP server.

Webhook events

Publishing, scheduled publishing, and release publishing all run the same publish path, so subscribers see the ordinary events:

ActionEvent
Publish, scheduled publish, release publishcontent.published
Unpublish, scheduled unpublishcontent.unpublished
Draft savecontent.saved

A payload produced by a scheduled single-entry action also carries scheduled: true. Every payload includes the resolved urls and stable revalidationTags for the affected entry, and events are emitted after the derived summaries and indexes are written, so a subscriber that refetches on delivery sees fresh artifacts. There is no separate release event: one content.published arrives per member. See Webhooks.

Rebuilds stay manual

Scheduled actions and releases never trigger a rebuild. Publishing converges the summaries and indexes for the entries involved, but a model-wide rebuild of summaries, field indexes, or list indexes is always an explicit call you make after changing model configuration. See Summaries and indexes.