Skip to content

Powered by Grav + Helios

Package Manager

Package Manager

Endpoints for managing Grav packages (plugins and themes) via the GPM, including installation, removal, updates, and repository search, plus the endpoints that serve plugin admin pages and web component scripts to Admin2.

Endpoints for managing Grav packages (plugins and themes) via the GPM, including installation, removal, updates, and repository search, plus the endpoints that serve plugin admin pages and web component scripts to Admin2.

List Plugins

GET /gpm/plugins
List all installed plugins with enablement flags, update status, and whether each plugin is installed via a symlink (important for upgrade gating — symlinked packages should not be overwritten). Requires `api.gpm.read`.
JSON
{"data": [{"slug": "simplesearch", "name": "SimpleSearch", "version": "3.0.0", "type": "plugin", "description": "A simple search plugin for Grav.", "description_html": "<p>A simple search plugin for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-simplesearch", "enabled": true, "is_symlink": false, "available_version": "3.0.1", "updatable": true}]}

Response Codes

200 Plugins returned.
401 Unauthorized.
403 Missing `api.gpm.read` permission.

Each entry is a package object. version is the installed version; available_version appears only when updatable is true. Optional blueprint fields (docs, bugs, dependencies, compatibility, keywords, icon) appear only when the plugin sets them, and premium plugins add premium, licensed, and when known vendor and purchase_url. A plugin whose settings are drawn on an admin page adds settings_route (a hash route) and, when that page belongs to another plugin, settings_page. A name or description written as a translation key is translated into the caller's admin language.

Get Plugin

GET /gpm/plugins/{slug}
Get details for a single installed plugin: the same package object as List Plugins, plus `custom_fields` when the plugin ships Admin Next field components. Requires `api.gpm.read`.

Parameters

Name Type Description
slug required string The plugin slug.
JSON
{"data": {"slug": "simplesearch", "name": "SimpleSearch", "version": "3.0.0", "type": "plugin", "description": "A simple search plugin for Grav.", "description_html": "<p>A simple search plugin for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-simplesearch", "enabled": true, "is_symlink": false, "available_version": "3.0.1", "updatable": true, "custom_fields": {"simplesearch-preview": "simplesearch-preview"}}}

Response Codes

200 Plugin returned.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.gpm.read` permission.
404 Plugin not installed.

The response carries an ETag header. Send it back as If-None-Match and the API answers 304 Not Modified with an empty body when nothing changed. custom_fields maps each field type the plugin ships under admin-next/fields/ to itself.

Install Package

POST /gpm/install
Install a plugin or theme from the GPM repository, along with any dependencies it needs. Requires `api.gpm.write`. Fires `onApiBeforePackageInstall` and `onApiPackageInstalled`.

Parameters

Name Type Description
package required string Package slug to install
type optional string Package type: `plugin` (default) or `theme`
license optional string Licence key for a premium package. It is saved only when the slug names a real package, and removed again if the install fails.
JSON
{"package": "sitemap", "type": "plugin"}
JSON
{"data": {"message": "Plugin 'sitemap' installed successfully.", "package": "sitemap", "type": "plugin", "dependencies": []}}

Response Codes

201 Package installed. `dependencies` lists any dependencies that were installed or updated along with it.
401 Unauthorized
403 Missing `api.gpm.write` permission
422 Validation error (invalid type, already installed, malformed licence key, premium package without a licence, or dependency/requirement check failed)
500 Installation failed. The message names any dependencies that were installed before the failure.

Remove Package

POST /gpm/remove
Remove an installed plugin or theme. Requires `api.gpm.write`. Fires `onApiBeforePackageRemove` and `onApiPackageRemoved`.

Parameters

Name Type Description
package required string Package slug to remove
JSON
{"package": "sitemap"}

Response Codes

204 Package removed
401 Unauthorized
403 Missing `api.gpm.write` permission
404 Package not installed
422 Missing `package` field
500 Removal failed. The error message is plain text, with GPM's console colour codes removed.

Check Updates

GET /gpm/updates
Check for available updates across plugins, themes, and the Grav core. Only packages with an update are listed. `total` counts Grav itself as well as plugin/theme updates. The `grav` object includes `is_symlink` so admin UIs can disable the core-upgrade action when Grav is symlinked. Requires `api.gpm.read`.

Parameters

Name Type Description
flush optional boolean Refresh the cached GPM repository data before checking.
JSON
{"data": {"grav": {"current": "2.1.0", "available": "2.1.1", "updatable": true, "date": "2026-09-18", "is_symlink": false}, "plugins": [{"slug": "form", "name": "Form", "version": "8.1.0", "type": "plugin", "description": "Enables forms handling and processing.", "description_html": "<p>Enables forms handling and processing.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-form", "enabled": true, "is_symlink": false, "available_version": "8.1.1", "updatable": true}], "themes": [], "total": 2, "installed": 14}}

Response Codes

200 Update summary returned.
401 Unauthorized.
403 Missing `api.gpm.read` permission.

In grav, current is the installed version and available the latest in the repository (null when the repository could not be read). In plugins and themes, each entry is a package object where version is the installed version and available_version the new one. installed is the number of installed plugins and themes combined.

Search Repository

GET /gpm/search
Search the GPM repository for plugins and themes. Plugins are listed before themes, and each result carries an `installed` flag. Requires `api.gpm.read`.

Parameters

Name Type Description
q required string Search query string, matched against name, slug and description
page optional integer Page number for pagination (default: 1)
per_page optional integer Number of results per page (default: 20, max: 1000)
JSON
{"data": [{"slug": "simplesearch", "name": "SimpleSearch", "version": "3.0.1", "type": "plugin", "description": "A simple search plugin for Grav.", "description_html": "<p>A simple search plugin for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-simplesearch", "installed": true}], "meta": {"pagination": {"page": 1, "per_page": 20, "total": 1, "total_pages": 1}}, "links": {"self": "/api/v1/gpm/search?page=1&per_page=20"}}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.gpm.read` permission
422 Missing `q` parameter

List Themes

GET /gpm/themes
List all installed themes with thumbnail and screenshot URLs, update status, and the `is_symlink` flag. For themes, `enabled` means it is the active theme. Requires `api.gpm.read`.
JSON
{"data": [{"slug": "quark", "name": "Quark", "version": "2.0.4", "type": "theme", "description": "Quark is the default theme for Grav.", "description_html": "<p>Quark is the default theme for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-theme-quark", "enabled": true, "is_symlink": false, "updatable": false, "thumbnail": "/api/v1/thumbnails/8c1f2a9e4b.jpg", "screenshot": "/api/v1/thumbnails/0d3e7b61fa.jpg"}]}

Response Codes

200 Themes returned.
401 Unauthorized.
403 Missing `api.gpm.read` permission.

thumbnail (capped at 500px) and screenshot (capped at 2000px) are /thumbnails/{file} URLs made from the theme's own thumbnail and screenshot images. When a theme has only one of the two, both fields use it; with neither, both are null.

Get Theme

GET /gpm/themes/{slug}
Get details for a specific installed theme: the same package object as List Themes, plus `custom_fields` when the theme ships Admin Next field components. Requires `api.gpm.read`.

Parameters

Name Type Description
slug required string The theme slug.
JSON
{"data": {"slug": "quark", "name": "Quark", "version": "2.0.4", "type": "theme", "description": "Quark is the default theme for Grav.", "description_html": "<p>Quark is the default theme for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-theme-quark", "enabled": true, "is_symlink": false, "updatable": false, "thumbnail": "/api/v1/thumbnails/8c1f2a9e4b.jpg", "screenshot": "/api/v1/thumbnails/0d3e7b61fa.jpg"}}

Response Codes

200 Theme returned.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.gpm.read` permission.
404 Theme not installed.

The response carries an ETag header. Send it back as If-None-Match and the API answers 304 Not Modified with an empty body when nothing changed.

Update Package

POST /gpm/update
Update a specific installed plugin or theme to the latest version, installing or updating any dependencies it needs first. Requires `api.gpm.write`. Fires `onApiBeforePackageUpdate` and `onApiPackageUpdated`.

Parameters

Name Type Description
package required string Package slug to update
JSON
{"package": "form"}
JSON
{"data": {"message": "Package 'form' updated successfully.", "package": "form", "type": "plugin", "dependencies": []}}

Response Codes

200 Package updated
401 Unauthorized
403 Missing `api.gpm.write` permission
404 Package not installed
422 Package already up to date, or a dependency/requirement check failed
500 Update failed. The message names any dependencies that were installed before the failure.

Update All Packages

POST /gpm/update-all
Update every updatable plugin and theme in one request, using fresh repository data. Each package is attempted independently — one failure does not abort the batch. Requires `api.gpm.write`.
JSON
{"data": {"updated": ["simplesearch", "seo-magic"], "failed": [{"package": "broken-plugin", "error": "Dependency unmet"}], "skipped": [{"package": "form", "reason": "already up to date (installed as a dependency)"}], "cascaded_dependencies": ["form"]}}

Response Codes

200 Batch completed; per-package outcome in `updated[]` / `failed[]` / `skipped[]`.
401 Unauthorized.
403 Missing `api.gpm.write` permission.

The response has four arrays:

  • updated: slugs that were updated.
  • failed: objects with package and error for packages whose requirements weren't met or whose update failed.
  • skipped: objects with package and reason for packages already brought up to date as a dependency of an earlier package in the batch.
  • cascaded_dependencies: slugs installed or updated as dependencies along the way.

Browse Repository Themes

GET /gpm/repository/themes
List all themes available in the GPM repository with `installed` flag on each. Supports pagination and `q` text search. 502 if the repository is unreachable. Requires `api.gpm.read`.

Parameters

Name Type Description
q optional string Search query to filter themes (matches name / slug / description).
page optional integer Page number (default 1).
per_page optional integer Items per page (default from config; max 2000 so the install modal can fetch the full list).
JSON
{"data": [{"slug": "quark", "name": "Quark", "version": "2.0.4", "type": "theme", "description": "Quark is the default theme for Grav.", "description_html": "<p>Quark is the default theme for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-theme-quark", "screenshot": "https://getgrav.org/images/quark-screenshot.jpg", "installed": true}], "meta": {"pagination": {"page": 1, "per_page": 20, "total": 120, "total_pages": 6}}, "links": {"self": "/api/v1/gpm/repository/themes?page=1&per_page=20", "next": "/api/v1/gpm/repository/themes?page=2&per_page=20", "last": "/api/v1/gpm/repository/themes?page=6&per_page=20"}}

Response Codes

200 Repository themes returned.
401 Unauthorized.
403 Missing `api.gpm.read` permission.
502 GPM repository unreachable.

In repository results version is the latest version in the repository and screenshot is the full URL of the repository screenshot. Premium themes add premium, licensed, and when known vendor and purchase_url.

Get README

GET /gpm/plugins/{slug}/readme
Get the raw README.md content for an installed plugin or theme. Also available at `/gpm/themes/{slug}/readme`. Requires `api.gpm.read`.

Parameters

Name Type Description
slug required string The package slug
JSON
{"data": {"content": "# My Plugin\n\nThis plugin does..."}}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.gpm.read` permission
404 Package or README not found
422 Invalid package slug

Get Changelog

GET /gpm/plugins/{slug}/changelog
Get the raw CHANGELOG.md content for an installed plugin or theme. Also available at `/gpm/themes/{slug}/changelog`. Requires `api.gpm.read`.

Parameters

Name Type Description
slug required string The package slug
JSON
{"data": {"content": "# v1.2.0\n## 01/15/2025\n\n* Added feature X..."}}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.gpm.read` permission
404 Package or changelog not found
422 Invalid package slug

Get Plugin Page

GET /gpm/plugins/{slug}/page
Get the admin page definition for a plugin. Returns the page type, blueprint reference, data/save endpoints, and action buttons. Resolution order: 1) onApiPluginPageInfo event, 2) admin-next/pages/{slug}.yaml, 3) admin-next/pages/{slug}.js (inferred component mode). Requires only `api.access`; the data behind the page answers to the plugin's own permissions.

Parameters

Name Type Description
slug required string The plugin slug
JSON
{"data": {"id": "license-manager", "plugin": "license-manager", "title": "License Manager", "icon": "fa-key", "page_type": "blueprint", "blueprint": "licenses", "data_endpoint": "/licenses/form-data", "save_endpoint": "/licenses", "actions": [{"id": "save", "label": "Save", "icon": "fa-check", "primary": true}], "has_custom_component": false}}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.access` permission
404 No admin page found for plugin

A definition may also carry settings_route, a hash route inside the page where the plugin's settings are drawn, and settings_page, the slug of another installed plugin whose admin page draws them. settings_page is kept only together with a valid settings_route.

Get Plugin Page Script

GET /gpm/plugins/{slug}/page-script
Serve the page-level web component JavaScript file for a plugin. The file is loaded from `admin-next/pages/{slug}.js` within the plugin directory.

Parameters

Name Type Description
slug required string Plugin slug.

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Plugin not installed or not enabled, or no page component.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

Get Grav Changelog

GET /gpm/grav/changelog
Get the Grav core changelog for every release newer than the installed version, joined into one Markdown document with a `# v{version} ({date})` heading per release. `content` is an empty string when Grav is up to date. Requires `api.gpm.read`.

Parameters

Name Type Description
flush optional boolean Refresh the cached GPM repository data first.
JSON
{"data": {"content": "# v2.1.1 (09/18/2026)\n\n1. [](#bugfix)\n    * Fixed ..."}}

Response Codes

200 Success
401 Unauthorized
403 Missing `api.gpm.read` permission

Upgrade Grav Core

POST /gpm/upgrade
Self-upgrade the Grav core. Refuses to run when Grav is installed via symlink (typical dev/monorepo setups). Runs the upgrade preflight checks first. Requires `api.gpm.write`. Fires `onApiBeforeGravUpgrade` and `onApiGravUpgraded` around the upgrade.

Parameters

Name Type Description
override optional boolean Upgrade even when the preflight checks report blocking problems.
JSON
{"override": false}
JSON
{"data": {"message": "Grav upgraded successfully.", "previous_version": "2.1.0", "new_version": "2.1.1"}}

Response Codes

200 Core upgraded.
401 Unauthorized.
403 Missing `api.gpm.write` permission.
409 Blocked by the preflight checks. The body lists the problems; retry with `override: true` to upgrade anyway.
422 Grav is already at the latest version, or installed via symlink.
500 Upgrade failed mid-flight.

When the preflight checks block the upgrade, the 409 response is a normal data payload rather than an error:

JSON
{
    "data": {
        "status": "preflight_failed",
        "message": "Upgrade blocked by preflight checks.",
        "blocking": [
            "Some enabled plugins/themes have not been marked as compatible with Grav 2.2. Disable them before continuing."
        ],
        "warnings": [],
        "incompatible_packages": { "target": "2.2" },
        "can_override": true
    }
}

Direct Install

POST /gpm/direct-install
Install a plugin or theme from a URL or uploaded zip — bypasses the GPM repository lookup. Accepts either a JSON body with `url`, or a multipart upload with a `file` field. Useful for private/unpublished packages, pre-release builds, or local development. Requires `api.gpm.write`.

Parameters

Name Type Description
url optional string An `http://` or `https://` URL of the package zip (mutually exclusive with `file`). Paths on the server are refused; upload a local zip as `file` instead.
file optional file Uploaded zip file (multipart; mutually exclusive with `url`).
JSON
{"url": "https://downloads.example.com/builds/my-plugin-1.0.0.zip"}
JSON
{"data": {"message": "Package installed successfully via direct install."}}

Response Codes

201 Package installed.
401 Unauthorized.
403 Missing `api.gpm.write` permission.
422 Neither `url` nor a valid `file` was provided, or `url` is not an http(s) address.
500 Installation failed.

List Repository Plugins

GET /gpm/repository/plugins
List all plugins available in the GPM repository, with `installed` flag on each. Supports pagination (`page`, `per_page` — capped at 2000 so the install modal can fetch the full list) and `q` text search. 502 if the repository is unreachable. Requires `api.gpm.read`.

Parameters

Name Type Description
page optional integer Page number (default 1).
per_page optional integer Items per page (default from config; max 2000).
q optional string Search filter matched against name / slug / description.
JSON
{"data": [{"slug": "simplesearch", "name": "SimpleSearch", "version": "3.0.1", "type": "plugin", "description": "A simple search plugin for Grav.", "description_html": "<p>A simple search plugin for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-simplesearch", "keywords": ["search", "plugin"], "installed": true}], "meta": {"pagination": {"page": 1, "per_page": 50, "total": 250, "total_pages": 5}}, "links": {"self": "/api/v1/gpm/repository/plugins?page=1&per_page=50", "next": "/api/v1/gpm/repository/plugins?page=2&per_page=50", "last": "/api/v1/gpm/repository/plugins?page=5&per_page=50"}}

Response Codes

200 Repository plugins returned.
401 Unauthorized.
403 Missing `api.gpm.read` permission.
502 GPM repository unreachable.

In repository results version is the latest version in the repository. To compare with what is installed, use List Plugins or Check Updates. Premium plugins add premium, licensed, and when known vendor and purchase_url.

Get Repository Package

GET /gpm/repository/{slug}
Get full repository details for a plugin or theme (whichever matches the slug), plus an `installed` flag. Requires `api.gpm.read`.

Parameters

Name Type Description
slug required string Package slug.
JSON
{"data": {"slug": "simplesearch", "name": "SimpleSearch", "version": "3.0.1", "type": "plugin", "description": "A simple search plugin for Grav.", "description_html": "<p>A simple search plugin for Grav.</p>", "author": {"name": "Team Grav", "email": "[email protected]", "url": "https://getgrav.org"}, "homepage": "https://github.com/getgrav/grav-plugin-simplesearch", "keywords": ["search", "plugin"], "installed": true}}

Response Codes

200 Package found.
401 Unauthorized.
403 Missing `api.gpm.read` permission.
404 Package not found in the GPM repository.

Get Custom Field Script

GET /gpm/plugins/{slug}/field/{type}
Serve the JavaScript web component for a plugin's custom blueprint field type. Also available under `/gpm/themes/{slug}/field/{type}` for theme-provided fields. Admin2 loads these on demand when rendering a blueprint that uses an unknown field type. Convention: the file lives at `admin-next/fields/{type}.js` inside the package. Unlike the other script endpoints, this one also serves a disabled plugin's fields, so its settings form can be edited before it is enabled.

Parameters

Name Type Description
slug required string Plugin (or theme) slug.
type required string Field type identifier (matches the `type:` value in the blueprint).

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Package or field component not found.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

Get Report Script

GET /gpm/plugins/{slug}/report-script/{reportId}
Serve the web component for a custom report shown on the Admin2 Reports page. Plugins ship the file at `admin-next/reports/{reportId}.js` and register the report via the `onApiGenerateReports` event. Admin2 loads the script only when the matching report is rendered.

Parameters

Name Type Description
slug required string Plugin slug.
reportId required string Report identifier (matches the `id` from `onApiGenerateReports`).

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Plugin not installed or not enabled, or report component not found.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

Get Floating Widget Script

GET /gpm/plugins/{slug}/widget-script
Serve the web component for a plugin-provided floating widget. Convention: the file lives at `admin-next/widgets/{slug}.js`. Registered via the `onApiFloatingWidgets` event and listed by `GET /floating-widgets`.

Parameters

Name Type Description
slug required string Plugin slug.

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Plugin not installed or not enabled, or widget component not found.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

Get Context Panel Script

GET /gpm/plugins/{slug}/panel-script
Serve the web component for a plugin-provided context panel (right-rail panel shown while editing pages or other content). Convention: the file lives at `admin-next/panels/{slug}.js`. Registered via the `onApiContextPanels` event and listed by `GET /context-panels`.

Parameters

Name Type Description
slug required string Plugin slug.

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Plugin not installed or not enabled, or panel component not found.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

GET /gpm/plugins/{slug}/modal-script/{modalId}
Serve the web component for a plugin-provided modal dialog. Convention: the file lives at `admin-next/modals/{modalId}.js` and is mounted as the custom element `grav-{slug}--modal-{modalId}`. Opened from a plugin web component via `window.__GRAV_DIALOGS.open()`, or directly from a menubar item carrying a `modal` intent. A plugin can ship several distinct modals, each with its own `modalId`.

Parameters

Name Type Description
slug required string Plugin slug.
modalId required string Modal component id — the basename of the file under `admin-next/modals/`.

Response Codes

200 JavaScript file served.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Plugin not installed or not enabled, or modal component not found.

Requires only api.access, so any admin who can reach the plugin's screens can load them without package manager rights. The script is served as application/javascript with Cache-Control: private, no-cache and an ETag built from the file's modification time and size, so a repeat request with If-None-Match gets an empty 304 until the file changes.

Get Custom Field Bundle

GET /gpm/plugins/{slug}/fields
Serve all of a package's custom field web components in one response, as a JSON object mapping each field type to its JavaScript source. Admin2 fetches this once per package instead of one request per field type. Also available at `/gpm/themes/{slug}/fields`. Served for disabled plugins too, so their settings forms stay editable.

Parameters

Name Type Description
slug required string Plugin (or theme) slug.
JSON
{"seo-magic-preview": "class SeoMagicPreview extends HTMLElement { ... }", "seo-magic-keywords": "class SeoMagicKeywords extends HTMLElement { ... }"}

Response Codes

200 Bundle served. An empty object when the package ships no field components.
304 Not modified. The `If-None-Match` header matches the current ETag.
401 Unauthorized.
403 Missing `api.access` permission.
404 Package not found.
422 Invalid package slug.

The body is the bare JSON map, not wrapped in the usual data envelope. It is served with Cache-Control: private, no-cache and an ETag built from each file's name, modification time and size, so revalidating costs only a 304 until a field file changes. Requires only api.access.