Skip to main content

REST API Reference

Shio has four HTTP surfaces, and picking the right one is most of the work:

SurfacePathUse it when
Delivery (CDA)/api/v2/cda/**, /graphqlYou are building a front end. Read-only, cacheable, documented here
Agent/api/v2/agent/**You are building an agent. Addressed, atomic, self-describing, documented here
MCPPOST /mcpYour client speaks MCP, documented here
Console/api/v2/**This page. What the React console calls: id-keyed CRUD, administration

If you are writing a script or an integration, the agent surface is almost always the better target: it addresses content by path, it is transactional, and its errors tell you how to fix them. The console API is here because the console uses it and because some administrative capabilities live only here.


Authentication

CallerHow
The consoleSession cookie + CSRF token (POST /api/v2/login)
A scriptHTTP Basic against the same endpoints
A non-browser caller on the agent or delivery surfacesA Key header, no cookie and no CSRF: see Security

The console API is session-shaped: it expects a cookie and a CSRF token on writes. That is deliberate, and it is the reason the agent surface exists as a stateless alternative rather than as a convenience wrapper.


Posts

One controller owns posts, in both states, at /api/v2/post-unified:

MethodPathDoes
POST/api/v2/post-unifiedCreate
GET/{id}Read one
PUT/{id}Update
DELETE/{id}Move to the trash
GET/folder/{folderId}List a folder's posts (paged)
POST/{id}/publishPublish the draft
POST/{id}/unpublishWithdraw the published row
POST/{id}/schedulePublish (or unpublish) at a timestamp
GET/{id}/versionsVersion history
POST/{id}/restoreRestore an earlier version
GET/trashWhat is in the trash
POST/{id}/untrashTake it back out
DELETE/{id}/purgeRemove permanently
GET/{id}/translationsSibling pages in other locales
POST/{id}/translateCreate a translation sibling

Objects: listings, copy, move, ACL

/api/v2/object handles the operations that apply to anything addressable: a post, a folder, a site:

MethodPathDoes
GET/{id}/listThe console listing for a container (paged)
GET/{id}/pathBreadcrumb
PUT/copyto/{destId}Copy the given objects into a destination
PUT/moveto/{destId}Move them
GET PUT/{id}/aclRead and set content permissions
GET/{id}/clear-cacheDrop cached renders for an object

Copy and move authorize both ends (the source and the destination) and a copy takes names that are free rather than overwriting.

Folders

MethodPathDoes
GET/api/v2/folder/{id}Read one
POST/{parentFolderId}Create beneath a parent
PUT/{id}Rename or update
DELETE/{id}Move the subtree to the trash
GET/{id}/pathBreadcrumb
GET/trash · POST /{id}/untrash · DELETE /{id}/purgeThe trash, for folders

Sites

MethodPathDoes
GET/api/v2/siteList
GET/{id}Read one, accepts an id, a friendly URL or a name
POST/api/v2/siteCreate (seeded from the bootstrap template)
PUT/{id}Update, including the post-type → layout bindings
DELETE/{id}Delete the site and everything in it
GET/{id}/exportDownload the site as an exchange package (application/zip)

POST /api/v2/import accepts one of those packages back.

Post types

One name-keyed surface. There is no id-keyed twin:

MethodPathDoes
GET/api/v2/post-typeList every type
GET/{name}One type and its fields
POST/api/v2/post-typeCreate
PUT/{name}Replace the definition
POST/{name}/renameRename: a move, keeping the type's content
DELETE/{name}Delete; a type content points at answers a teaching 409

A type marked managed by code refuses a console PUT with a 409: it is owned by shio push, and the console shows it read-only rather than letting two writers race.

Static files

/api/v2/staticfile/** uploads and manages file bytes. An upload creates a File post, and the bytes are then reachable two ways:

URLFor
/file_source/{postId}/{fileName}The canonical, id-keyed path
/sites/{site}/{folder-chain}/{fileName}The same bytes at the path the site's own structure implies

Both accept transform parameters, ?w=, ?h=, ?format=, ?crop=.

The rest

RootOwns
/api/v2/render/post-typesProvision the render model; /drift and /reconcile
/api/v2/reviewReview sessions: list, read, approve, revert
/api/v2/historyThe audit trail
/api/v2/api-token · /preview-tokenAPI keys and short-lived preview tokens
/api/v2/site-webhookPer-site webhook subscriptions
/api/v2/widgetThe widget catalogue a post type's fields reference
/api/v2/group · /roleUsers, groups and roles
/api/v2/localeThe locale axis
/api/v2/tenantTenants (admin): see Multi-Tenancy
/api/v2/provider/auth · /provider/exchange · /config/emailConfiguration providers
/api/v2/discovery · /system/info · /pingInstance metadata and health
/api/v2/setupFirst-run setup

Interactive documentation for every endpoint above is served by the instance itself at /swagger-ui.html, generated from the controllers, which makes it the authority when this page and the tree disagree.


Three endpoints that do not exist

An absence cannot be discovered by reading, so it is worth stating. Inventing one of these is the most common wrong turn:

Does not existUse instead
POST /api/v2/postPOST /api/v2/post-unified, or post.upsert on the agent surface
DELETE /api/v2/object/{id}Delete by type: DELETE /api/v2/post-unified/{id} or DELETE /api/v2/folder/{id}
A console post-type controller at /api/v2/post/type/api/v2/post-type/**: the id-keyed twin was retired

PageDescription
The Agent SurfaceThe addressed, transactional alternative
Content Delivery APIThe read-only delivery contract
SecuritySessions, tokens, scopes, CSRF and CORS
Administration GuideWhat these endpoints look like in the console