API reference

Integrate catalogues and publishing pipelines with saved IIIF content, explicit release targets, build inventories, and the hosted editing protocols used by the web interface.

Version 1JSON over HTTPSIIIF Presentation 3Web interface guide

Overview

The public integration workflow is intentionally small: discover a token's site, read its current revision, write resources at that revision, capture the release target, then build that exact target.

1
Discover
List the site and read its current saved resources.
2
Write
Create, replace, or delete at the revision you just read.
3
Capture
Read the open release ID and target fingerprint.
4
Build
Queue Preview or Live for that exact immutable target.

Authentication

Create site-scoped credentials from Account settings → API tokens. Tokens are displayed once, stored only as a SHA-256 hash, and take effect or stop working on the next request.

Bearer tokens
Send the full iiif_pat_… value in every request. Token names are up to 80 characters and expiry is 1–365 days.
HTTP
Authorization: Bearer iiif_pat_replace_me
FieldGrantsDescription
site:readReadList the assigned site, saved resources, current release, inventories, references, and build screenshots.
resource:writeEditCreate, update, and delete resources for the assigned site. Does not imply site:read.
release:writePublishQueue Preview or Live builds for an explicit release target. Does not imply site:read.
  • Tokens are restricted to one site.
  • Revoked and expired tokens fail immediately.
  • Locked accounts cannot use existing tokens.
  • Losing workspace membership invalidates access.
  • Browser sessions may use the account endpoints without Authorization.
  • Malformed bearer syntax is a 400; a well-formed unknown token is a 401.

Quick start

1. Configure and discover

shell
export IIIF_SITE_API=https://app.iiif.site
export IIIF_SITE_TOKEN=iiif_pat_replace_me

curl --fail-with-body \
  -H "Authorization: Bearer $IIIF_SITE_TOKEN" \
  "$IIIF_SITE_API/api/v1/sites"

2. Create a resource

shell
curl --fail-with-body \
  -X POST \
  -H "Authorization: Bearer $IIIF_SITE_TOKEN" \
  -H "Content-Type: application/json" \
  "$IIIF_SITE_API/api/v1/sites/$IIIF_SITE_ID/resources" \
  --data '{
    "revision": 3,
    "slug": "turner-sketchbook",
    "mode": "copy",
    "document": {
      "id": "https://example.org/iiif/turner-sketchbook",
      "type": "Manifest",
      "label": { "en": ["Turner sketchbook"] },
      "items": []
    }
  }'

3. Build the release

shell
release=$(curl --fail-with-body \
  -H "Authorization: Bearer $IIIF_SITE_TOKEN" \
  "$IIIF_SITE_API/api/v1/sites/$IIIF_SITE_ID/releases/current")

# Read id and targetFingerprint from $release, then:
curl --fail-with-body \
  -X POST \
  -H "Authorization: Bearer $IIIF_SITE_TOKEN" \
  -H "Content-Type: application/json" \
  "$IIIF_SITE_API/api/v1/sites/$IIIF_SITE_ID/releases/$RELEASE_ID/builds" \
  --data '{"channel":"preview","targetFingerprint":"'$TARGET_FINGERPRINT'"}'

Resource model

A site owns a versioned list of directly managed resources. Build inventories then expand those inputs into the complete graph actually shipped by Preview or Live.

FieldTypeDescription
idUUIDStable internal resource ID used by update, delete, references, and authored content.
slugstringStable site-relative identifier: lowercase letters, numbers, and hyphens, maximum 80 characters.
typeManifest | CollectionValidated IIIF Presentation resource type.
storagecopied | remoteCopied resources store an editable document; remote references store an upstream URL and are read-only.
sourceUrlURL?Upstream import/reference URL when the resource originated elsewhere.
documentobject?Complete IIIF document, present only for copied resources.
createdAt / updatedAtISO 8601Saved-resource timestamps used by destination-change comparisons.
Saved content
Direct copied and remote inputs at a numeric content revision.
Release target
Content, design, settings, and template captured behind a SHA-256 fingerprint.
Build inventory
Immutable expanded graph, including generated and nested remote resources.

Publishing API

The supported unattended integration surface for site discovery, managed IIIF content, release inspection, and builds.

GET/api/v1/sites
List accessible sites
Discovers site IDs and current content revisions. A bearer token returns only the site it was created for; a browser session returns every accessible site.
Authentication
Browser session or a token with site:read.
Response
{ sites: [{ id, name, slug, revision }] } in newest-first order.

Statuses: 200, 400, 401, 403

GET/api/v1/sites/:siteId/resources
Read the current saved content
Returns the current optimistic-concurrency revision and all directly managed IIIF resources.
Authentication
Browser session or a token with site:read for this site.
Response
site contains id, name, slug, revision, Preview/Live hostnames and activation state, plus whether fixed pages are editable. resources contains copied and remote resource records.
Notes
Read this endpoint immediately before every write. Never guess or increment a stale revision.

Statuses: 200, 400, 401, 403, 404

POST/api/v1/sites/:siteId/resources
Create a copied resource or remote reference
Adds a complete IIIF Presentation 3 Manifest or Collection at the supplied revision.
Authentication
Browser session or a token with resource:write for this site.
Request
JSON with revision, slug, optional mode (copy orremote), and either documentor sourceUrl. Remote mode requires a source URL. If mode is omitted it defaults to copied import behavior.
Response
{ revision, resources } for the new saved revision, including the generated resource UUID.
Notes
Slugs are lowercase letters, numbers, and single hyphens, up to 80 characters; collection is reserved. Presentation 2 input is upgraded before Presentation 3 validation. Workspace resource quotas apply.

Statuses: 201, 400, 401, 403, 409, 422, 429

PUT/api/v1/sites/:siteId/resources/:resourceId
Update a copied resource
Replaces the stored IIIF document and may change its slug. Remote references are intentionally read-only.
Authentication
Browser session or a token with resource:write for this site.
Request
JSON with revision, slug, and a complete document.
Response
{ revision, resources }
Notes
A duplicate slug returns already_exists. To edit a remote reference, delete it and recreate it as a copy, or use Make editable copy in the web interface.

Statuses: 200, 400, 401, 403, 404, 409, 422

DELETE/api/v1/sites/:siteId/resources/:resourceId
Delete a managed resource
Removes a saved resource at the current revision after reference-safety checks pass.
Authentication
Browser session or a token with resource:write for this site.
Request
The non-negative current revision in the revisionquery parameter. There is no request body.
Response
{ revision, resources }
Notes
Deletion is rejected while a page, post, Page Block, featured-resource setting, or Madoc connection still references the resource.

Statuses: 200, 400, 401, 403, 404, 409

GET/api/v1/sites/:siteId/releases/current
Read the open release target
Captures the exact content, settings, template, and design target that Preview or Live should build.
Authentication
Browser session or a token with site:read for this site.
Response
Release id, number, optional name and notes, target version and SHA-256 fingerprint, baseline publication, Preview freshness and build IDs, structured delta, summary, and recent release activity.
Notes
Preview freshness is needs_preview, building, failed, or current. Save both id and targetFingerprint for an explicit build request.

Statuses: 200, 400, 401, 403, 404

POST/api/v1/sites/:siteId/releases/:releaseId/builds
Build an explicit release target
Queues Preview or Live without racing later edits. Identical non-failed targets are idempotent.
Authentication
Browser session or a token with release:write for this site.
Request
Strict JSON with channel set topreview or production, and the 64-character targetFingerprint returned by the current-release endpoint. The API value productionis labelled Live in the interface.
Response
{ id, existing }. A new build returns 201; an already queued, running, or indexed successful build returns 200 withexisting: true.
Notes
If saved work changed after you read the release, the server returns release_target_conflict. Fetch the release again and make an explicit decision about the new target.

Statuses: 200, 201, 400, 401, 403, 404, 409

Inventory and diagnostics

Read the versioned graph produced by a build, locate authored dependencies, and fetch the screenshot used by the dashboard.

GET/api/v1/sites/:siteId/resources/inventory
List a build resource inventory
Browses the IIIF graph materialized by an active Preview/Live deployment or an immutable historical build.
Authentication
Browser session or a token with site:read for this site.
Request
Query parameters: channel=preview|production(default Preview), or buildId for history; optional q, type,storage, status,changed=true|false, and positivepage. A buildId takes precedence over channel.
Response
Inventory metadata, matching nodes, total, page, andpageSize: 50. With no filters, the result is the graph roots. If the selected build exists but predates inventory indexing,inventory is null andunindexedBuild describes it.

Statuses: 200, 400, 401, 403, 404, 422

GET/api/v1/sites/:siteId/resources/inventory/:nodeKey
Read one inventory node
Loads a stable graph node with lazy hierarchy, authored references, and comparison state.
Authentication
Browser session or a token with site:read for this site.
Request
A 32-character lowercase hexadecimal node key. Acceptschannel or buildId and an optional positive childPage.
Response
Inventory metadata, node, up to 50 direct children, parent nodes, breadcrumbs, child pagination, change-since-Live state, source/build details, and deduplicated page/post/Page Block references.

Statuses: 200, 400, 401, 403, 404, 422

GET/api/v1/sites/:siteId/references
Read the authored reference index
Explains which authored site content points to each managed IIIF resource.
Authentication
Browser session or a token with site:read for this site.
Response
{ version: 1, references, byTarget }. References identify their source type, label, dashboard URL, resource ID, field, and optional language. Sources include pages, posts, Page Blocks, featured resources, and Madoc.

Statuses: 200, 400, 401, 403, 404

GET/api/v1/sites/:siteId/builds/:buildId/screenshot
Read a deployment screenshot
Returns the JPEG captured for an accessible deployed build. This supports the account UI and is not a core integration contract.
Authentication
Browser session or a token with site:read for this site.
Response
image/jpeg, limited to 2 MB, with ETag and Last-Modified validators.
Notes
If-None-Match may return 304. Missing, undeployed, invalid, or oversized screenshots return plain-text 404 rather than the JSON error envelope.

Statuses: 200, 304, 400, 401, 403, 404

Manifest Editor capability

This short-lived protocol is created by the web interface for one copied resource. It is documented for completeness, not as a replacement for API tokens.

OPTIONSGETPOST/api/v1/editor-sessions/:token/resource
Hosted Manifest Editor capability
A one-hour, resource-specific capability used by the web interface to open a copied resource in the configured Manifest Editor.
Authentication
The unguessable token in the path; account API tokens and cookies are not used.
Request
GET has no body. POST sends the complete IIIF document as the JSON body, not a wrapper object. OPTIONS performs the editor CORS preflight.
Response
GET returns the raw IIIF document and anX-IIIF-Post-Url header. POST returns the normal saved-content { revision, resources } result. OPTIONS returns 204 for the configured Manifest Editor origin and 403 for other origins.
Notes
The capability is valid only for copied resources, the creating user must remain unlocked with edit access, writes use the session's tracked content revision, and responses are no-store.

Statuses: 200, 204, 400, 403, 404, 409, 422

Page Blocks editing

The design editor uses a two-step, origin-bound capability flow. Dashboard control routes require a browser session; Preview-side routes require the issued session bearer and the exact verified Preview origin.

POST/api/v1/sites/:siteId/page-blocks/editor-sessions
Create a design-editor launch
Creates a single-use launch URL for a template that supports Preview design editing.
Authentication
Browser session with edit permission. API tokens are not accepted.
Response
{ url, expiresAt }
Notes
The launch token expires after two minutes and requires an active Preview deployment. The URL opens the private Preview and carries the token in the fragment.

Statuses: 200, 400, 401, 404

OPTIONSPOST/api/v1/page-blocks/sessions/exchange
Exchange a launch token
Turns the single-use launch token into an origin-bound eight-hour editor session.
Authentication
Allowed verified Preview origin plus the launch token in the request body.
Request
Strict JSON { launchToken }; token length is 32–200 characters. The request must include the exact PreviewOrigin.
Response
Session token, site and design revision state, expiry, dashboard URL, allowed origin, template key/revision, and capabilitiesblocks:read, blocks:write, and preview:build.

Statuses: 200, 204, 401, 403, 422

OPTIONSGETDELETE/api/v1/page-blocks/session
Inspect or revoke a design-editor session
Reads current session/revision state or revokes the editor session immediately.
Authentication
Origin-bound Page Blocks bearer session.
Response
GET returns the same session details as exchange. DELETE returns{ success: true }. OPTIONS returns the origin-specific CORS preflight.

Statuses: 200, 204, 401, 403

OPTIONSPOST/api/v1/page-blocks
Page Blocks service protocol
Executes the installed page-blocks service request envelope for the session's site and template directory.
Authentication
Origin-bound Page Blocks bearer session.
Request
The page-blocks client protocol envelope. Operations are validated against the active template directory and scoped to the session site; do not construct envelopes from untrusted client state.
Response
The page-blocks protocol response for reads and writes. Successful writes create versioned design documents and advance the site's design revision.
Notes
CORS allows only the exact verified Preview origin, Authorization and Content-Type headers, and GET/POST/DELETE/OPTIONS methods. Responses are no-store.

Statuses: 200, 204, 400, 401, 403, 409, 422

OPTIONSPOST/api/v1/page-blocks/build-preview
Build the edited Preview
Queues a Preview build for the editor session's site after design changes are saved.
Authentication
Origin-bound Page Blocks bearer session.
Response
{ id, existing }
Notes
No request body. The normal build rate limit and idempotency rules apply.

Statuses: 200, 204, 400, 401, 403, 429

GET/api/v1/sites/:siteId/page-blocks/revisions
List design revision history
Returns the current design revision and grouped historical operations for the active template revision.
Authentication
Browser session with view permission. API tokens are not accepted.
Response
{ currentRevision, revisions: [{ revision, createdAt, operations }] }

Statuses: 200, 401, 404

POST/api/v1/sites/:siteId/page-blocks/revert
Restore an earlier design revision
Copies the chosen earlier state into a new revision; later history is retained.
Authentication
Browser session with edit permission. API tokens are not accepted.
Request
{ revision: non-negative integer }
Response
{ revision, restoredRevision }
Notes
The target must be earlier than the current revision and must produce a real change.

Statuses: 200, 400, 401, 404, 422

POST/api/v1/sites/:siteId/page-blocks/starters
Apply a starter design
Applies a template-supplied set of Page Block documents as one new design revision.
Authentication
Browser session with edit permission. API tokens are not accepted.
Request
{ starterId, expectedRevision }
Response
{ revision, starterId }
Notes
The body is strict. A changed design returns revision_conflict; a changed template returns template_changed. Starter IDs and documents are validated against the current template directory.

Statuses: 200, 400, 401, 404, 409, 422

System routes

Operational and browser-session routes included here so the reference covers every current API route file.

GET/api/health
Application health
Checks application routing and a live database query.
Authentication
None.
Response
{ ok: true }
Notes
A database failure produces a server error and is intended for deployment health checks.

Statuses: 200, 500

GETPOST/api/auth/*
Browser session service
The Better Auth handler used by sign-in, sign-out, session, and password flows in the web interface.
Authentication
Varies by Better Auth operation.
Request
Operation-specific Better Auth request. Use the bundled web client rather than treating these routes as a versioned integration API.
Response
Operation-specific Better Auth response and secure session cookies.
Notes
This wildcard is included for route coverage, but it is not the site publishing API. Server integrations should use site-scoped iiif_pat_ bearer tokens.

Statuses: Operation-specific

Errors

Except for binary screenshot misses and third-party auth operations, API failures use one JSON envelope.

json
{
  "error": {
    "code": "revision_conflict",
    "message": "Content changed while you were editing"
  }
}
FieldHTTPDescription
malformed_bearer / invalid_json / bad_request400Bearer syntax, JSON parsing, or a request-specific precondition failed.
unauthorized / invalid_token / invalid_launch_token401Authentication is missing, invalid, expired, revoked, or already exchanged.
account_locked / wrong_site / insufficient_scope / invalid_origin403The credential is known but cannot perform this operation or originate here.
not_found404The accessible site, resource, release, inventory, build, or session does not exist.
revision_conflict / release_target_conflict / already_exists / template_changed409Refresh state or choose a different unique identifier before retrying.
invalid_request422Schema, query, slug, IIIF document, or strict-object validation failed.
quota_exceeded429A workspace resource limit was reached. Build and token creation also have operation-specific rate limits.
internal_error500A database or unexpected server failure was hidden behind a safe message.

Endpoint index

Every currently registered API route and method is represented below. OPTIONS is shown where the route implements an explicit CORS preflight.

MethodPathPurpose
GET/api/v1/sitesList accessible sites
GET/api/v1/sites/:siteId/resourcesRead the current saved content
POST/api/v1/sites/:siteId/resourcesCreate a copied resource or remote reference
PUT/api/v1/sites/:siteId/resources/:resourceIdUpdate a copied resource
DELETE/api/v1/sites/:siteId/resources/:resourceIdDelete a managed resource
GET/api/v1/sites/:siteId/releases/currentRead the open release target
POST/api/v1/sites/:siteId/releases/:releaseId/buildsBuild an explicit release target
GET/api/v1/sites/:siteId/resources/inventoryList a build resource inventory
GET/api/v1/sites/:siteId/resources/inventory/:nodeKeyRead one inventory node
GET/api/v1/sites/:siteId/referencesRead the authored reference index
GET/api/v1/sites/:siteId/builds/:buildId/screenshotRead a deployment screenshot
OPTIONS/api/v1/editor-sessions/:token/resourceHosted Manifest Editor capability
GET/api/v1/editor-sessions/:token/resourceHosted Manifest Editor capability
POST/api/v1/editor-sessions/:token/resourceHosted Manifest Editor capability
POST/api/v1/sites/:siteId/page-blocks/editor-sessionsCreate a design-editor launch
OPTIONS/api/v1/page-blocks/sessions/exchangeExchange a launch token
POST/api/v1/page-blocks/sessions/exchangeExchange a launch token
OPTIONS/api/v1/page-blocks/sessionInspect or revoke a design-editor session
GET/api/v1/page-blocks/sessionInspect or revoke a design-editor session
DELETE/api/v1/page-blocks/sessionInspect or revoke a design-editor session
OPTIONS/api/v1/page-blocksPage Blocks service protocol
POST/api/v1/page-blocksPage Blocks service protocol
OPTIONS/api/v1/page-blocks/build-previewBuild the edited Preview
POST/api/v1/page-blocks/build-previewBuild the edited Preview
GET/api/v1/sites/:siteId/page-blocks/revisionsList design revision history
POST/api/v1/sites/:siteId/page-blocks/revertRestore an earlier design revision
POST/api/v1/sites/:siteId/page-blocks/startersApply a starter design
GET/api/healthApplication health
GET/api/auth/*Browser session service
POST/api/auth/*Browser session service

The route inventory contains 20 route files and 30 registered HTTP methods, including five explicit CORS preflights and the two-method browser auth wildcard.