Domma CMS User Manual

Plugins API

Updated by Darryl Waterhouse on 29 September 2026 5 min read

These endpoints drive the Marketplace screen (System > Plugins, #/plugins). They need the plugins permission for the action named: read, create (install), update (switch on or off, settings) or develop (the source editor, export and restart). Installing from, and uninstalling through, the managed catalogue needs an admin (role level 0 or 1).

Restarts. A plugin's routes and screens are read when the server starts, so switching a plugin or a built-in Tool on or off restarts the server by itself, about a second and a half after the reply, when something will bring it back (the fleet manager, or pm2) and restartOnPluginToggle in config/server.json is not false. The reply says what happened: restartRequired, supervised, restarting. Installing, updating and uninstalling do not restart; the new code runs after the next restart.

GET /api/plugins

Requires Bearer token + plugins read permission.

Every installed plugin, with its state.

// Response 200
[ { "name": "blog", "displayName": "Blog", "version": "1.9.0", "description": "...", "author": "...", "icon": "edit",
    "core": false, "enabled": true, "closedSource": false, "licence": "...",
    "entitlement": null,          // for a licensed plugin: valid, grace, expired, support-ended, unlicensed...
    "supersededBy": null,         // enabled but replaced by another plugin (a Pro edition)
    "blockedBy": null,            // enabled but not running: something it requires is off
    "locked": false,              // the site's manager holds this switch
    "requires": [], "uses": {},
    "settings": {}, "settingsSchema": null, "effectiveSettings": {} } ]

Secret settings come back masked; sending the mask back keeps the stored value.

PUT /api/plugins/:name

Requires Bearer token + plugins update permission.

Switch a plugin on or off, or save its settings. A switch goes through the same check as the screen: a switch the site's manager has locked is refused with 423, and one that changes other Tools or plugins (a plugin that requires this one goes off with it; switching one on brings on what it requires) answers 409 with the plan until repeated with "cascade": true. A built-in plugin cannot be switched off.

FieldTypeDescription
enabledbooleanOn or off
settingsobjectThe plugin's settings
cascadebooleanConfirm the knock-on changes in a 409's plan
// Response 200 - a switch
{ "success": true, "restartRequired": true, "supervised": true, "restarting": true }
// Error 409 - confirm first
{ "error": "This switch changes other Tools too.", "needsConfirm": true, "plan": { ... } }

GET /api/tools

Requires Bearer token + plugins read permission.

The built-in Tools that can be switched off - Contacts, Notes, Todo, Analytics and SEO - with their state and the plugins that depend on each. GET /api/tools/enabled (any signed-in user) answers just {"notes": true, ...}.

// Response 200
[ { "name": "contacts", "displayName": "Contacts", "enabled": true, "locked": false,
    "requiredBy": [ { "name": "contacts-pro", "displayName": "Contacts Pro" } ],
    "usedBy": [ { "name": "calendar", "displayName": "Calendar", "reason": "Invite a contact group" } ] } ]

PUT /api/tools/:name

Requires Bearer token + plugins update permission.

Switch a built-in Tool on or off ({"enabled": false}). Nothing is deleted; switched back on, everything is where it was. The same 423 / 409-with-plan / cascade rules and restart as a plugin.

POST /api/plugins/install-upload

Requires Bearer token + plugins create permission. Content-Type: multipart/form-data.

Install or update a plugin from a .dcmsplugin file (Install from file). The plugin is named by the manifest inside, not the file name. Refusals come back as questions to confirm with form fields set to true: confirmUpgrade (it is already installed - 409, code: "already-installed"), confirmDowngrade and confirmUnsigned (a file not signed by the Marketplace; a site with requireSignedPlugins refuses those outright). A plugin whose minCmsVersion is newer than this site is refused, naming both versions, and an update leaves the installed version in place. A licensed plugin's licence travels in the file. A new plugin arrives switched off.

// Response 200
{ "success": true, "name": "invoices", "action": "install", "from": null, "version": "1.6.1", "restartRequired": true }
// Error 400
{ "error": "Invoices needs Domma CMS 0.93.0 or later; this site runs 0.92.2. Update the CMS first." }

GET /api/plugins/marketplace

Requires Bearer token + an admin role (level 0 or 1).

The Browse tab: what this site can get from its manager, with what is installed and what can be updated. A site that is not managed answers {"available": false, "catalogue": []} and installs from a file instead.

cmsVersion is the Domma CMS this site runs. Each entry's needsCms is null, or - when the plugin's minCmsVersion is newer than this site - the sentence an install would be refused with.

// Response 200
{ "available": true, "site": "my-site", "cmsVersion": "0.94.0",
  "catalogue": [ { "slug": "invoices", "version": "1.6.1", "installed": true, "installedVersion": "1.6.0", "updatable": true, "needsCms": null, ... } ] }

POST /api/plugins/marketplace/install

Requires Bearer token + an admin role (level 0 or 1). Managed sites only.

Fetch a plugin from the manager and install it, licensed to this site; "update": true updates one already installed. If the update fails, the installed version is put back. A refusal from the manager (no licence) answers 403 with its reason; 503 when the manager cannot be reached. A plugin that needs a newer Domma CMS answers 400 naming both versions, as Install from file does.

// Request body
{ "slug": "invoices", "version": "1.6.1", "update": true }
// Response 200
{ "success": true, "name": "invoices", "action": "upgrade", "from": "1.6.0", "version": "1.6.1", "restartRequired": true }
// Error 400
{ "error": "SEO Pro needs Domma CMS 0.90.0 or later; this site runs 0.89.2. Update the CMS first." }

DELETE /api/plugins/marketplace/:slug

Requires Bearer token + an admin role (level 0 or 1).

Uninstall a plugin. Its files and its data/ folder are removed, roles it added are removed and their users moved to user. Restart to finish.

// Response 200
{ "success": true }

GET /api/plugins/admin-config

Requires Bearer token (any role).

What the admin needs from the running plugins: sidebar items, screens (routes) and the scripts behind them.

// Response 200
{ "sidebar": [ { "id": "blog", "text": "Blog", "icon": "edit", "url": "#/plugins/blog" } ],
  "routes": [ { "path": "/plugins/blog", "view": "plugin-blog", "title": "Blog - Domma CMS" } ],
  "views": { "plugin-blog": { "entry": "blog/admin/views/blog.js", "exportName": "blogView" } } }

POST /api/plugins/scaffold

Requires Bearer token + plugins create permission.

Start a new plugin from the template (New plugin). It is created switched on and runs after the next restart.

// Request body
{ "slug": "my-plugin", "displayName": "My Plugin", "description": "...", "author": "...", "icon": "package" }
// Response 200
{ "success": true, "name": "my-plugin", "files": [ ... ], "restartRequired": true }

GET /api/plugins/:name/export

Requires Bearer token + plugins develop permission.

Download a plugin as an unsigned .dcmsplugin file (?includeData=1 adds its data). Licensed plugins cannot be exported (403). The source editor uses GET /api/plugins/:name/files and GET, PUT, DELETE /api/plugins/:name/file, and POST /api/plugins/restart restarts the server to run edited code; a licensed plugin's source is open only to the level-0 role.