Skip to main content

Plugins API

Manage plugins, execute actions, and monitor jobs through the REST API.

Plugin Management

List Plugins

GET /v1/plugins/manage

Returns all discovered plugins with their current state (enabled/disabled), metadata, and settings.

curl http://localhost:8181/v1/plugins/manage
[
{
"name": "image-processor",
"version": "1.0.0",
"description": "Processes images using external APIs",
"enabled": true,
"settings": [
{ "name": "api_key", "type": "password", "label": "API Key", "required": true }
]
}
]

Enable Plugin

POST /v1/plugin/enable
Content-Type: application/x-www-form-urlencoded
ParameterTypeDescription
namestringPlugin name to enable
curl -X POST http://localhost:8181/v1/plugin/enable \
-d "name=image-processor"

Required settings must be saved before enabling. Returns an error if required settings are missing.

Disable Plugin

POST /v1/plugin/disable
Content-Type: application/x-www-form-urlencoded
ParameterTypeDescription
namestringPlugin name to disable
curl -X POST http://localhost:8181/v1/plugin/disable \
-d "name=image-processor"

Disabling removes all hooks, injections, pages, menus, and actions. In-flight async actions are awaited before the Lua VM is closed.

Save Plugin Settings

POST /v1/plugin/settings?name={pluginName}
Content-Type: application/json
ParameterLocationTypeDescription
namequery or formstringPlugin name
(body)JSON bodyobjectSetting key-value pairs
curl -X POST "http://localhost:8181/v1/plugin/settings?name=image-processor" \
-H "Content-Type: application/json" \
-d '{
"api_key": "sk-abc123",
"model": "quality",
"max_size": 2048
}'

Settings are validated against the plugin's declared setting definitions. Unknown keys are ignored. Boolean settings must be native JSON booleans (true/false, not strings). Number settings must be native JSON numbers (2048, not "2048").

Purge Plugin Data

Delete all key-value store data for a plugin. The plugin must be disabled before purging.

POST /v1/plugin/purge-data
Content-Type: application/x-www-form-urlencoded
ParameterTypeDescription
namestringPlugin name to purge data for
curl -X POST http://localhost:8181/v1/plugin/purge-data \
-d "name=image-processor"

Response:

{
"ok": true,
"name": "image-processor"
}
warning

Purging deletes all KV store entries for the plugin. This action is irreversible. The plugin must be disabled first; attempting to purge an enabled plugin returns an error.

Plugin Actions

List Available Actions

GET /v1/plugin/actions
ParameterTypeRequiredDescription
entitystringYes"resource", "note", or "group"
content_typestringNoFilter by Resource content type
category_iduintNoFilter by Group Category ID
note_type_iduintNoFilter by Note Type ID
curl "http://localhost:8181/v1/plugin/actions?entity=resource&content_type=image/jpeg"
[
{
"plugin_name": "image-processor",
"id": "colorize",
"label": "Colorize Image",
"entity": "resource",
"placement": ["detail", "card"],
"async": true,
"params": [
{ "name": "style", "type": "select", "label": "Style", "options": ["realistic", "artistic"] }
]
}
]

Run an Action

POST /v1/jobs/action/run
Content-Type: application/json
{
"plugin": "image-processor",
"action": "colorize",
"entity_ids": [42],
"params": {
"style": "realistic"
}
}

Sync actions return 200 OK:

{
"success": true,
"message": "Image colorized",
"redirect": "/resource?id=42"
}

Async actions return 202 Accepted:

{
"job_id": "a1b2c3d4e5f6g7h8"
}

Bulk execution (multiple entity_ids) returns wrapped results:

  • Sync actions: { "results": [...] }
  • Async actions: { "job_ids": [...] }

The bulk_max limit on the action registration is enforced.

Get Action Job Status

GET /v1/jobs/action/job
ParameterTypeDescription
idstringJob ID
curl "http://localhost:8181/v1/jobs/action/job?id=a1b2c3d4e5f6g7h8"
{
"id": "a1b2c3d4e5f6g7h8",
"source": "plugin",
"pluginName": "image-processor",
"actionId": "colorize",
"label": "Colorize Image",
"entityId": 42,
"entityType": "resource",
"status": "running",
"progress": 65,
"message": "Applying color model...",
"createdAt": "2025-03-01T10:30:00Z"
}

Plugin Block Rendering

GET /v1/plugins/{pluginName}/block/render

Renders a plugin-defined block type as an HTML fragment. The block editor's frontend calls this endpoint to display plugin blocks.

ParameterLocationTypeRequiredDescription
pluginNamepathstringYesThe plugin that registered the block type
blockIdqueryintegerYesThe block to render
modequerystringYes"view" or "edit"
curl "http://localhost:8181/v1/plugins/my-plugin/block/render?blockId=42&mode=view"

Returns text/html content. The block's type must start with plugin:<pluginName>:, otherwise a 400 error is returned.

See Custom Block Types for details on how plugin block rendering works.

Plugin Pages

GET|POST /plugins/{pluginName}/{path}

Plugin-registered pages are served at this path. The response is HTML generated by the plugin's page handler.

curl http://localhost:8181/plugins/image-processor/dashboard

Plugin JSON API Endpoints

GET|POST|PUT|DELETE /v1/plugins/{pluginName}/{path}

Plugin-registered JSON API endpoints. Unlike plugin pages (which return HTML), these return application/json responses.

# GET endpoint
curl http://localhost:8181/v1/plugins/my-plugin/stats

# POST with JSON body
curl -X POST http://localhost:8181/v1/plugins/my-plugin/webhook \
-H "Content-Type: application/json" \
-d '{"event": "test"}'

Success Response:

{
"total_notes": 42,
"query": { "page": "1" }
}

Error Responses:

StatusConditionBody
400Handler called mah.abort(){"error": "reason"}
404Plugin not found or path not registered{"error": "plugin not found"} or {"error": "endpoint not found"}
405Path exists but method not registered{"error": "method not allowed"}
500Handler runtime error{"error": "internal plugin error"}
504Handler exceeded timeout{"error": "handler timed out"}

See Plugin Lua API Reference for the mah.api() registration function.

Unified Job Endpoints

The queue endpoint returns download jobs only. Plugin action jobs appear in the SSE event stream alongside download events.

List Download Jobs

GET /v1/jobs/queue
curl http://localhost:8181/v1/jobs/queue

Returns the retained download jobs currently held in the queue manager, including completed, failed, cancelled, or paused jobs until their retention window expires. Plugin action jobs are not included here; they are available only via the SSE event stream below.

SSE Event Stream

GET /v1/jobs/events

Server-Sent Events stream for all job types. The stream uses SSE event names to distinguish job types.

Download events use event names added, updated, removed:

event: updated
data: {"type":"updated","job":{"id":"abcd1234","status":"downloading","progress":45}}

Plugin action events use event names action_added, action_updated, action_removed:

event: action_updated
data: {"job":{"id":"a1b2c3d4e5f6g7h8","source":"plugin","status":"running","progress":65}}

Initialization: On connect, an init event is sent with all current jobs:

event: init
data: {"jobs":[...],"actionJobs":[...]}