Docs

How Dezignee works.

One document engine, several ways to drive it. Everything below is the model shared by the embed, the MCP servers, and the REST API — the plugin reference lives on its own page.

The model

Commands in, patches out.

Clients send intent, not diffs. The backend validates, applies, and versions it, then answers with RFC 6902 JSON patches plus a sequenceVersionId you apply to local state. Manual edits, AI chat, MCP tools — all one pipeline, no second write path.

Request

{
  "baseVersionId": "v_8f21…",
  "commands": [
    {
      "type": "ELEMENT_UPDATE",
      "elementId": "el_hero_cta",
      "props": { "text": "Finish setup" }
    }
  ]
}

Response

{
  "patch": [
    { "op": "replace",
      "path": "/body/rows/0/columns/0/elements/2/text",
      "value": "Finish setup" }
  ],
  "sequenceVersionId": "v_8f22…",
  "warnings": []
}

Document shape

body → rows[] → columns[] → elements[], every node globally id'd. Element types: heading, text, image, button, divider, spacer.

Two resources

A template is one email. A sequence is an ordered set of templates. Commands and undo/redo are sequence-level — this surprises people.

Command types

ELEMENT_UPDATE · ELEMENT_INSERT · ELEMENT_DELETE · ROW_INSERT · ROW_DELETE · ROW_MOVE · META_UPDATE

Embed

The plugin has its own reference.

Install, session minting, the three integration paths, theming, custom asset storage, streaming, export, framework recipes, and security — all on one page.

dezignee-plugin

An iframe plus a postMessage bridge, no runtime dependencies. Distributed on npm and on cdn.dezignee.com, with TypeScript types.

Plugin reference

MCP

Two servers, split by trust level.

One helps developers build the embed and can only read. One assists with design and can write commands. Install only what you need.

setup & inspectionRead-only

For Cursor and VS Code. No command emission at all — it cannot change a document.

detect_projectinstall_bridgecreate_embed_componentconfigure_initsecure_postmessage_allowlistwire_asset_adapterworkspace_overviewlist_sequenceslist_emailslist_assetsget_audit_eventsdiagnostics
design & commandsRead-write

For Claude Desktop and SaaS integrations. Chat an email into existence from scratch — it emits the same typed commands the editor does, so every change is versioned and undoable.

suggest_copysuggest_layoutsuggest_stylesgenerate_commandsapply_commandsapply_ai_suggestion

Connect a client

{
  "mcpServers": {
    "dezignee": {
      "command": "pipx",
      "args": [
        "run", "dezignee-mcp-servers", "users",
        "--code=dzg_mcp_your-one-time-code"
      ]
    }
  }
}

Resources are URI-addressed

workspace://{id}
email://{id}
sequence://{id}

The one-time code comes from the dashboard under Settings → Connect MCP and is valid for 5 minutes. It is exchanged on first run for credentials stored in ~/.dezignee/.

Claude DesktopCursorVS CodeAny MCP client

Auth

Three token types.

API key

dzg_api_…

Backend-minted, shown once. Server-side only — it mints sessions and never enters a browser.

Session token

short-lived

What the plugin's init() takes. Your backend calls POST /api/v1/sessions with the API key and hands this to the frontend.

MCP one-time code

dzg_mcp_…

Valid 5 minutes, exchanged on first run for stored credentials.

Mint a session

curl -X POST https://api.dezignee.com/api/v1/sessions \
  -H "Authorization: Bearer $DEZIGNEE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "workspaceId": "ws_123", "actorRef": "user_456" }'

# → { "sessionId": "…", "workspaceId": "ws_123", "actorRef": "user_456" }

workspaceId is the tenancy boundary and is enforced at the API level — a session cannot reach across workspaces.

REST surface

The endpoints you'll actually call.

Server-to-server, authenticated with your API key. The plugin uses these on your behalf; you need them directly for backend exports, provisioning, and automation.

EndpointPurpose
POST /api/v1/sessionsMint a session token for the plugin.
POST /api/v1/sequencesCreate a sequence. The plugin does this for you when sequenceId is omitted.
POST /api/v1/sequences/{sequenceId}/commandsApply commands. Returns patch + sequenceVersionId + warnings[].
POST /api/v1/ai/chatSSE stream behind editor.chat().
GET /api/v1/templates/{templateId}/export-htmlBackend-source HTML for one template, no live editor needed.

Merge tags are literal {{ first_name }} tokens in subject, text, and link fields, resolved at render. Export results carry per-item warnings[] from inbox validation.

Versions

Every mutation is a version.

Conflict detection

Requests carry baseVersionId. A stale base is rejected rather than silently overwriting someone else's edit.

Undo / redo

Sequence-level, max 10 steps, and only available when the editor was initialised with a sequenceId.

Retention

Last 200 drafts per document, all published versions, and all named snapshots.

Ready to embed it?

The quickstart is three steps and takes an afternoon end to end.