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.
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.
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.
iiif_pat_… value in every request. Token names are up to 80 characters and expiry is 1–365 days.Authorization: Bearer iiif_pat_replace_me| Field | Grants | Description |
|---|---|---|
| site:read | Read | List the assigned site, saved resources, current release, inventories, references, and build screenshots. |
| resource:write | Edit | Create, update, and delete resources for the assigned site. Does not imply site:read. |
| release:write | Publish | Queue 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
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
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
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'"}'409 revision_conflict means another writer saved first. GET the resources again, reapply your intended change to the returned content, and retry with that revision. Do not blindly increment the rejected value.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.
| Field | Type | Description |
|---|---|---|
| id | UUID | Stable internal resource ID used by update, delete, references, and authored content. |
| slug | string | Stable site-relative identifier: lowercase letters, numbers, and hyphens, maximum 80 characters. |
| type | Manifest | Collection | Validated IIIF Presentation resource type. |
| storage | copied | remote | Copied resources store an editable document; remote references store an upstream URL and are read-only. |
| sourceUrl | URL? | Upstream import/reference URL when the resource originated elsewhere. |
| document | object? | Complete IIIF document, present only for copied resources. |
| createdAt / updatedAt | ISO 8601 | Saved-resource timestamps used by destination-change comparisons. |
Publishing API
The supported unattended integration surface for site discovery, managed IIIF content, release inspection, and builds.
/api/v1/sites{ sites: [{ id, name, slug, revision }] } in newest-first order.Statuses: 200, 400, 401, 403
/api/v1/sites/:siteId/resourcessite contains id, name, slug, revision, Preview/Live hostnames and activation state, plus whether fixed pages are editable. resources contains copied and remote resource records.Statuses: 200, 400, 401, 403, 404
/api/v1/sites/:siteId/resourcesrevision, 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.{ revision, resources } for the new saved revision, including the generated resource UUID.Statuses: 201, 400, 401, 403, 409, 422, 429
/api/v1/sites/:siteId/resources/:resourceIdrevision, slug, and a complete document.{ revision, resources }Statuses: 200, 400, 401, 403, 404, 409, 422
/api/v1/sites/:siteId/resources/:resourceIdrevisionquery parameter. There is no request body.{ revision, resources }Statuses: 200, 400, 401, 403, 404, 409
/api/v1/sites/:siteId/releases/currentStatuses: 200, 400, 401, 403, 404
/api/v1/sites/:siteId/releases/:releaseId/buildschannel set topreview or production, and the 64-character targetFingerprint returned by the current-release endpoint. The API value productionis labelled Live in the interface.{ id, existing }. A new build returns 201; an already queued, running, or indexed successful build returns 200 withexisting: true.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.
/api/v1/sites/:siteId/resources/inventorychannel=preview|production(default Preview), or buildId for history; optional q, type,storage, status,changed=true|false, and positivepage. A buildId takes precedence over channel.pageSize: 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
/api/v1/sites/:siteId/resources/inventory/:nodeKeychannel or buildId and an optional positive childPage.Statuses: 200, 400, 401, 403, 404, 422
/api/v1/sites/:siteId/references{ 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
/api/v1/sites/:siteId/builds/:buildId/screenshotStatuses: 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.
/api/v1/editor-sessions/:token/resourceX-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.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.
/api/v1/sites/:siteId/page-blocks/editor-sessions{ url, expiresAt }Statuses: 200, 400, 401, 404
/api/v1/page-blocks/sessions/exchange{ launchToken }; token length is 32–200 characters. The request must include the exact PreviewOrigin.blocks:read, blocks:write, and preview:build.Statuses: 200, 204, 401, 403, 422
/api/v1/page-blocks/session{ success: true }. OPTIONS returns the origin-specific CORS preflight.Statuses: 200, 204, 401, 403
/api/v1/page-blocksStatuses: 200, 204, 400, 401, 403, 409, 422
/api/v1/page-blocks/build-preview{ id, existing }Statuses: 200, 204, 400, 401, 403, 429
/api/v1/sites/:siteId/page-blocks/revisions{ currentRevision, revisions: [{ revision, createdAt, operations }] }Statuses: 200, 401, 404
/api/v1/sites/:siteId/page-blocks/revert{ revision: non-negative integer }{ revision, restoredRevision }Statuses: 200, 400, 401, 404, 422
/api/v1/sites/:siteId/page-blocks/starters{ starterId, expectedRevision }{ revision, starterId }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.
/api/health{ ok: true }Statuses: 200, 500
/api/auth/*Statuses: Operation-specific
Errors
Except for binary screenshot misses and third-party auth operations, API failures use one JSON envelope.
{
"error": {
"code": "revision_conflict",
"message": "Content changed while you were editing"
}
}| Field | HTTP | Description |
|---|---|---|
| malformed_bearer / invalid_json / bad_request | 400 | Bearer syntax, JSON parsing, or a request-specific precondition failed. |
| unauthorized / invalid_token / invalid_launch_token | 401 | Authentication is missing, invalid, expired, revoked, or already exchanged. |
| account_locked / wrong_site / insufficient_scope / invalid_origin | 403 | The credential is known but cannot perform this operation or originate here. |
| not_found | 404 | The accessible site, resource, release, inventory, build, or session does not exist. |
| revision_conflict / release_target_conflict / already_exists / template_changed | 409 | Refresh state or choose a different unique identifier before retrying. |
| invalid_request | 422 | Schema, query, slug, IIIF document, or strict-object validation failed. |
| quota_exceeded | 429 | A workspace resource limit was reached. Build and token creation also have operation-specific rate limits. |
| internal_error | 500 | A 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.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/sites | List accessible sites |
| GET | /api/v1/sites/:siteId/resources | Read the current saved content |
| POST | /api/v1/sites/:siteId/resources | Create a copied resource or remote reference |
| PUT | /api/v1/sites/:siteId/resources/:resourceId | Update a copied resource |
| DELETE | /api/v1/sites/:siteId/resources/:resourceId | Delete a managed resource |
| GET | /api/v1/sites/:siteId/releases/current | Read the open release target |
| POST | /api/v1/sites/:siteId/releases/:releaseId/builds | Build an explicit release target |
| GET | /api/v1/sites/:siteId/resources/inventory | List a build resource inventory |
| GET | /api/v1/sites/:siteId/resources/inventory/:nodeKey | Read one inventory node |
| GET | /api/v1/sites/:siteId/references | Read the authored reference index |
| GET | /api/v1/sites/:siteId/builds/:buildId/screenshot | Read a deployment screenshot |
| OPTIONS | /api/v1/editor-sessions/:token/resource | Hosted Manifest Editor capability |
| GET | /api/v1/editor-sessions/:token/resource | Hosted Manifest Editor capability |
| POST | /api/v1/editor-sessions/:token/resource | Hosted Manifest Editor capability |
| POST | /api/v1/sites/:siteId/page-blocks/editor-sessions | Create a design-editor launch |
| OPTIONS | /api/v1/page-blocks/sessions/exchange | Exchange a launch token |
| POST | /api/v1/page-blocks/sessions/exchange | Exchange a launch token |
| OPTIONS | /api/v1/page-blocks/session | Inspect or revoke a design-editor session |
| GET | /api/v1/page-blocks/session | Inspect or revoke a design-editor session |
| DELETE | /api/v1/page-blocks/session | Inspect or revoke a design-editor session |
| OPTIONS | /api/v1/page-blocks | Page Blocks service protocol |
| POST | /api/v1/page-blocks | Page Blocks service protocol |
| OPTIONS | /api/v1/page-blocks/build-preview | Build the edited Preview |
| POST | /api/v1/page-blocks/build-preview | Build the edited Preview |
| GET | /api/v1/sites/:siteId/page-blocks/revisions | List design revision history |
| POST | /api/v1/sites/:siteId/page-blocks/revert | Restore an earlier design revision |
| POST | /api/v1/sites/:siteId/page-blocks/starters | Apply a starter design |
| GET | /api/health | Application 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.