Maileditor Docs

Backend API

Server-to-server reads across a plugin's end users, authenticated with the Plugin ID and Secret.

Read-only endpoints for your own server. Every embedded endpoint answers for one end user; this surface reads every user's work, so it is authenticated with the Plugin Secret and refuses browsers. The integration guide is Backend API.

Paths use the prefix /plugin/v1/backend, not /public/plugin/v1. No CORS headers are sent.

Authentication

X-Plugin-Id: 9f3c1e7a-4b21-4c8e-9a77-1d2f5b6c8e10
X-Plugin-Secret: your_plugin_secret

Send both headers on every request; either one alone is refused. A session token is not accepted.

curl https://api.maileditor.net/api/plugin/v1/backend/users \
  -H 'X-Plugin-Id: 9f3c1e7a-4b21-4c8e-9a77-1d2f5b6c8e10' \
  -H 'X-Plugin-Secret: your_plugin_secret'

X-Plugin-Secret is not redacted by logging tools the way Authorization often is. If you log request headers, add it to your scrubbing list. Never put these credentials in a browser or a query string; query-string credentials are refused even when correct.

If your backend needs to act as one user rather than read about all of them, create a session with external_user_id set through the session endpoint and use the embedded endpoints.

Errors

StatuserrorMeaning
401credentials_requiredOne or both headers missing
401invalid_credentialsWrong secret, unknown plugin, or a suspended plugin
401credentials_in_queryCredentials sent as query parameters
409plugin_not_provisionedThe plugin's storage is still being set up. Retry shortly
429Rate limited. 60 per minute and 2000 per day per plugin id, failed attempts included

List users

GET /plugin/v1/backend/users
QueryNotes
searchSubstring of the id
per_pageDefault 25, capped at 100

200

{
  "message": "End users retrieved successfully",
  "result": {
    "users": {
      "data": [
        {
          "external_user_id": "user-42",
          "template_count": 7,
          "first_template_at": "2026-06-01T09:14:22.000000Z",
          "last_activity_at": "2026-08-28T16:02:11.000000Z"
        }
      ],
      "links": { "…": "…" },
      "meta": { "…": "…" }
    }
  }
}

Lists end users who have saved at least one template. A user who opened the editor and saved nothing does not appear, and anonymous sessions are excluded. last_activity_at is their last save. MailEditor holds no name or email; external_user_id is what you sent, echoed back.

List templates

GET /plugin/v1/backend/templates
QueryNotes
external_user_idOne user's work
searchOn name
updated_after, updated_beforeAny parseable date. For incremental sync
per_pageDefault 25, capped at 100

200 returns result.templates, paginated, each entry in the same shape as the embedded list. Without external_user_id you get every end user's templates.

Template details

GET /plugin/v1/backend/templates/{template}

200 returns result.template, including its external_user_id.

404 template_not_found for an unknown id or one belonging to another plugin.

Template HTML

GET /plugin/v1/backend/templates/{template}/html

200

{
  "result": {
    "template_id": 41,
    "external_user_id": "user-42",
    "source": "draft",
    "html": "<!doctype html>…"
  }
}

A draft saved seconds ago reads back here. source is draft until the file has been written, then media. The markup is current either way.

On this page