Reference Omeka S module

REST API

The module exposes a small JSON API under /api/page-versioning/. It is separate from Omeka's core /api endpoint and is aimed at scripts and integrations that need to read history or trigger a revert.

Authentication

These routes are not part of Omeka's core API route, so the key_identity and key_credential API key parameters are not recognised. Requests are authenticated with the normal Omeka S login session: call the endpoints from a browser that is logged in to the admin panel, or send the session cookie from your script.

Permissions are those of the history screens in the admin panel:

Endpoint Rule
List versions Author role or higher, otherwise 403. The page must also be readable by the requester; private pages return 404 to users who cannot see them
Get a version Author role or higher, otherwise 403
Revert Editor role or higher, otherwise 403. Omeka must also let the user change that page (a 403 otherwise)

Requests without a login session get a 403.

Response format

Successful responses:

{ "status": "ok", "data": { ... } }

Errors use an HTTP status code and this body:

{ "status": "error", "message": "Version #12 not found" }

Every response, error or not, is JSON with the content type application/json.

Status Meaning
400 Invalid ID, a JSON body that is not an object, or a summary that is not text
403 The user's role may not use the endpoint, or may not change the page
404 The page or version does not exist, or the page is not visible to the user
405 Wrong HTTP method
422 Omeka refused to save the page as it was in the version; see below
500 An unexpected error; the message says what failed and the error is written to Omeka's log

A revert that Omeka's validation refuses, typically because another page of the site now uses the version's slug, returns 422 with the reasons by field, as Omeka's own API does:

{
  "status": "error",
  "message": "The slug \"about\" is already taken.",
  "errors": { "o:slug": ["The slug \"about\" is already taken."] }
}

The page and its history are left as they were. Give the other page a different slug and try again.

List versions for a page

GET /api/page-versioning/{pageId}/versions
Query parameter Default Description
limit 50 Number of versions to return, 1 to 200
offset 0 Number of versions to skip
type site_page Resource type filter; only site_page is written by this module

Versions are returned newest first without their payload:

{
  "status": "ok",
  "data": {
    "resource_id": 42,
    "resource_type": "site_page",
    "total": 12,
    "limit": 50,
    "offset": 0,
    "versions": [
      {
        "id": "99",
        "resource_id": "42",
        "resource_type": "site_page",
        "title": "About the collection",
        "slug": "about",
        "operation": "update",
        "editor_id": "3",
        "editor_name": "Jane Doe",
        "summary": null,
        "created_at": "2026-03-15 14:30:00"
      }
    ]
  }
}

Numeric columns may be returned as strings, depending on the database driver.

Get a single version

GET /api/page-versioning/version/{versionId}

Returns the full row including the decoded payload (title, slug, is_public, layout, layout_data, blocks and site_id). The structure is the same as the JSON export described in Exporting and Deleting Versions.

Revert a page to a version

POST /api/page-versioning/version/{versionId}/revert
Content-Type: application/json

{ "summary": "Restoring the introduction paragraph" }

The body may be JSON or form encoded. summary is optional; when omitted the revert entry is noted as "Reverted to version #N (saved ...)". The response contains the ID of the new revert version:

{ "status": "ok", "data": { "new_version_id": 103 } }

The revert behaves exactly like a revert from the admin interface; see Reverting a Page.

Example

# Using a browser session cookie exported from the admin panel
curl -s -b "PHPSESSID=..." \
  "https://example.org/api/page-versioning/42/versions?limit=5" | python3 -m json.tool

Developer notes

  • Version capture is attached to the entity.persist.post and entity.update.post events for Omeka\Entity\SitePage and Omeka\Entity\SitePageBlock. Any save that goes through Omeka's entity manager is captured; direct SQL changes are not.
  • The service PageVersioning\Service\VersionManager is available from the service manager and provides listVersions(), getVersion(), diff(), revertToVersion(), deleteVersion() and captureFromPayload().
  • Versions are stored in the page_versions table with raw DBAL queries; there is no Doctrine entity.
Log in for Support