Publication management
Use publication routes to create a blog publication, manage its identity and
settings, and control whether it is available to public readers. A publication
has an operational status (active or disabled) and a separate archival
state. Only active, unarchived publications are available through public
resolution and public read routes.
Authentication
Every route except /publication/resolve requires a bearer token. The caller
needs the capability shown in the route table. Publication-specific requests
accept publication_id or publication_slug; use the stable ID after
creation.
Routes
| Route | Methods | Authorization | Required input | Optional input and behavior | Success result |
|---|---|---|---|---|---|
/publication/list |
GET, POST |
Authenticated principal | — | archived, pagination |
Paginated publications. |
/publication/get |
POST |
publication.get |
Publication selector | — | publication. |
/publication/create |
POST |
publication.create |
name |
slug, locale, initial settings groups |
Created publication and context. |
/publication/save |
POST |
publication.save |
Publication selector | name, slug, featured_media_id |
Saved publication. |
/publication/archive |
POST |
publication.archive |
Publication selector | — | Archived publication. |
/publication/restore |
POST |
publication.restore |
Publication selector | — | Restored publication. |
/publication/delete |
POST |
publication.delete |
Publication selector | — | Deleted publication_id. |
/publication/update-status |
POST |
publication.status |
Publication selector, status |
— | Updated publication. |
/publication/resolve |
POST |
None | publication_slug or slug |
— | Public publication identity. |
/publication/settings/get |
POST |
settings.get |
Publication selector | — | publication_id and settings. |
/publication/settings/save |
POST |
settings.save |
Publication selector and a settings update | locale shortcut |
Updated settings. |
Publication object
Management responses return this core shape; they can also include the
caller's role, scope, and capabilities.
{
"publication_id": "PUBLICATION_UUID",
"slug": "engineering-notes",
"name": "Engineering Notes",
"featured_media_id": "MEDIA_UUID",
"status": "active",
"archived": 0,
"archived_at": null,
"archive_note": null,
"created_at": "2026-08-19 00:00:00.000000",
"updated_at": "2026-08-19 00:00:00.000000"
}
Create and update
Create fields
| Field | Required | Type | Description |
|---|---|---|---|
name |
Yes | String | Publication name. |
slug |
No | String | Globally unique slug. Omit or send an empty value to derive it from name. |
locale |
No | String | Initial settings.identity.locale; letters, numbers, _, and - only. |
settings |
No | Object | Initial settings groups. |
identity, theme, seo, feeds, search, comments, subscriptions, notifications, integrations, metadata |
No | Object | Alternative top-level initial settings groups. |
curl -sS https://api.blog.service.m7.org/v1/publication/create \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name":"Engineering Notes",
"slug":"engineering-notes",
"locale":"en-US"
}'
New publications start active and unarchived. The creating principal becomes
its owner. Create rejects caller-supplied owner, status, archival, timestamp,
and featured_media_id fields.
Use /publication/save to update the identity:
{
"publication_id": "PUBLICATION_UUID",
"name": "Engineering Journal",
"slug": "",
"featured_media_id": "MEDIA_UUID"
}
The featured_media_id must reference ready media in the same publication.
An empty slug derives a new slug from the submitted name. Fields not sent are
retained; status and archival fields are rejected by this route.
Listing and public resolution
/publication/list defaults to unarchived publications. Send archived: 1
to list archived records, along with the standard pagination fields from the
service guide.
/publication/resolve is the unauthenticated lookup used before loading
public content:
{ "publication_slug": "engineering-notes" }
It returns 404 unless the publication is active and unarchived:
{
"public_publication": {
"publication_id": "PUBLICATION_UUID",
"slug": "engineering-notes",
"name": "Engineering Notes",
"created_at": "2026-08-19 00:00:00.000000",
"updated_at": "2026-08-19 00:00:00.000000"
}
}
Status and archival lifecycle
Use /publication/update-status to set status to exactly active or
disabled. This does not alter archival state.
{ "publication_id": "PUBLICATION_UUID", "status": "disabled" }
Archive and restore accept only a publication selector. Archiving preserves the
current status; restoring does the same. A publication must first be archived
before it can be permanently deleted. Deletion returns 409 while it still
has posts, pages, redirects, domains, authors, tags, categories, or media.
Settings
/publication/settings/get returns all groups. To update settings, send a
non-empty settings object or one or more top-level group objects. Updates
merge recursively with current settings.
{
"publication_id": "PUBLICATION_UUID",
"settings": {
"identity": { "locale": "en-US" },
"seo": { "title_suffix": "| Engineering" }
}
}
The allowed group names are identity, theme, seo, feeds, search,
comments, subscriptions, notifications, integrations, and metadata.
locale may be sent as a shortcut for identity.locale. Non-empty values
under sensitive-looking setting keys are returned as [redacted]; do not use a
redacted response as an input value when preserving a secret.