Package Information
Documentation
n8n-nodes-emdash
Consume and manage content, media, menus, schemas, taxonomies, search, URL redirects, comments, settings, sections, and widget areas from EmDash CMS in n8n workflows.
This is an independent Black Swamp AI community integration. It is not affiliated with, endorsed by, sponsored by, or maintained by EmDash or Cloudflare Inc. Product names and marks belong to their respective owners and are used only to identify compatibility.
Installation · Compatibility · Credentials · Operations · Migration · Usage · Troubleshooting · Resources · Black Swamp AI
Installation
On self-hosted n8n instances, install this community node through the n8n web interface:
- Open Settings → Community Nodes in your n8n workspace.
- Select Install a community node.
- Enter
@blackswampai/n8n-nodes-emdashin the npm package name field. - Agree to the risks of installing third-party code and select Install.
For additional guidance on managing community nodes, see the n8n Community Nodes installation documentation.
Compatibility
| Surface | Tested baseline | Notes |
|---|---|---|
| n8n | 2.30.6 | Runtime, picker-source, and user-verified picker baseline |
| EmDash CMS | v1 (emdash@1.0.1+) | Cloudflare Workers REST API endpoint |
| Node.js development | 22.22.0 and 24 | CI and package checks run on both lanes. |
Credentials
To authenticate with your EmDash instance:
EmDash API Credential
- In n8n, create an EmDash API credential.
- Site URL: Enter the root URL of your EmDash installation (for example,
https://cms.example.com). The node automatically normalizes trailing slashes and routes requests through the/_emdash/apiendpoint prefix. - API Token: Enter a Personal Access Token (PAT) generated in your EmDash administrative panel.
Personal Access Token Scopes and RBAC
EmDash 1.0.1 defines the following valid PAT scopes: content:read, content:write, media:read, media:write, schema:read, schema:write, taxonomies:manage, menus:manage, settings:read, settings:manage, mcp:tools, transfer:export, transfer:analyze, transfer:execute, and admin.
Effective authorization requires both the PAT scope and the user's underlying RBAC role. Scopes required by resource:
- Content operations:
- Read queries (
GET) requirecontent:read. Write and mutation operations (including creation, updates, publish, unpublish, schedule, unschedule, duplicate, restore, and permanent delete) requirecontent:write. (EmDash does not use a separatecontent:publishscope). - Editorial and collaboration operations:
- Get Translations: PAT
content:read, RBACcontent:read(non-published variants filtered withoutcontent:read_drafts). - Get Authors: PAT
content:read, RBACcontent:read_drafts(editorial draft visibility due to author PII and email). - Get Trashed: PAT
content:read, RBACcontent:read_drafts. - Get Edit Lock: PAT
content:read, RBACcontent:edit_own/content:edit_any. - Acquire Edit Lock: PAT
content:write, RBACcontent:edit_own/content:edit_any. - Release Edit Lock: PAT
content:write, RBACcontent:edit_own/content:edit_any.
- Get Translations: PAT
- Important note on token scopes: There is NO Personal Access Token scope named
content:read_drafts. Draft visibility is enforced via internal user RBAC role capabilities under thecontent:readPAT scope.
- Read queries (
- Media operations: Read queries (
GET) generally requiremedia:read, except Get Usage which requires Personal Access Token scopeadmin(notmedia:read) alongside RBAC capabilitiesmedia:read+content:read_drafts. For Get and Get Many withincludeUsage=1, an inline coverage-aware usage summary is returned, butusage.countis only readable when the caller holds both the RBACcontent:read_draftscapability and, when authenticated by a PAT/OAuth token, theadmintoken scope (amedia:readPAT alone cannot expose draft-derived usage counts). Mutations (binary uploads, staged upload target generation, raw chunk uploads, confirmation, image replacement, metadata updates, folder creation, folder rename, and file/folder deletion) requiremedia:write. - Menu operations:
- PAT scopes: Read queries (
GET) requirecontent:read. Write and mutation operations (POST,PUT,DELETE) requiremenus:manage(which is also implicitly granted bycontent:writeoradmin). EmDash does NOT definemenus:read,menu:read, ormenu:writeas Personal Access Token scopes. - RBAC permissions: The authenticated user must separately possess the
menus:readcapability for reads, andmenus:managecapability (Editor or Administrator role) for mutations.
- PAT scopes: Read queries (
- Taxonomy operations: Read queries (
GET) requirecontent:read. Bulk tagging requirescontent:write. Schema mutations and term management requiretaxonomies:manage(implicitly granted bycontent:writeoradmin). (EmDash does not definetaxonomy:readortaxonomy:writescopes). - Search operations: Queries and prefix suggestions require
content:read. Administrative operations (rebuilding an index or enabling search on a collection) requireadmin. (EmDash does not definesearch:readorsearch:adminscopes). - Redirect operations: Neither
redirects:readnorredirects:writeexists as a PAT scope. All redirect rules and 404 access log operations requireadmindue to fail-closed middleware scope enforcement. - Schema operations:
- PAT scopes: Read queries (
GET) requireschema:read(oradmin). Write and mutation operations (POST,PUT,DELETE) requireschema:write(oradmin). - RBAC permissions: Reads require the
schema:readcapability. Schema modifications requireschema:manage(Administrator or Developer role). - Write-only token discovery fallback: Tokens possessing only
schema:writecan execute mutations but cannot access read endpoints used by editorlistSearchselectors. Every collection and field resource locator provides a manual "By Slug" mode to allow workflow execution with write-only credentials.
- PAT scopes: Read queries (
- Comment moderation operations: EmDash does not define granular
comments:*PAT scopes (such ascomments:readorcomments:moderate). All comment moderation endpoints live under/_emdash/api/admin/commentsand strictly require a Personal Access Token with theadminscope in combination with administrative RBAC permissions. - Settings operations:
- PAT scopes: Read queries (
GET) requiresettings:read(oradmin). Update operations (POST) requiresettings:manage(oradmin). - RBAC permissions: The authenticated user must separately possess the
settings:readcapability for reads, andsettings:managecapability (Administrator role) for updates.
- PAT scopes: Read queries (
- Section operations:
- PAT scopes: Read queries (
GET) requirecontent:read. Write and mutation operations (POST,PUT,DELETE) requirecontent:write(oradmin). EmDash does not define separatesections:*PAT scopes. - RBAC permissions: The authenticated user must separately possess the
sections:readcapability for reads, andsections:managecapability (Editor or Administrator role) for mutations.
- PAT scopes: Read queries (
- Widget Area operations:
- PAT scopes: Read queries (
GET) requirecontent:read. Write and mutation operations (POST,PUT,DELETE) requirecontent:write(oradmin). EmDash does not define separatewidgets:*PAT scopes. - RBAC permissions: The authenticated user must separately possess the
widgets:readcapability for reads, andwidgets:managecapability (Editor or Administrator role) for mutations.
- PAT scopes: Read queries (
Operations
The EmDash community node provides 103 operations across 11 core resources:
Comment (6 operations)
- Get Many (
getAll): Retrieve comments with cursor pagination and status, collection, and search filters. - Get Counts (
getCounts): Retrieve comment counts grouped by moderation status (pending,approved,spam,trash). - Get (
get): Retrieve a single comment by ID including author metadata, IP hash, and status. - Update Status (
updateStatus): Update the moderation status of a comment (approved,pending,spam,trash). - Bulk Action (
bulkAction): Apply moderation action (approve,spam,trash) or permanently delete up to 100 comments in a single request. - Delete (
delete): Permanently delete a comment by ID (irreversible).
Content (22 operations)
- Get Many (
getAll): Retrieve entries in a collection with cursor pagination, publication status filtering, and date ranges. - Get (
get): Retrieve a single content item by ID or URL slug. - Create (
create): Create a draft content entry with JSON data, SEO metadata, locale, and taxonomy terms. - Update (
update): Mutate existing content with optimistic concurrency control (_rev). - Delete (
delete): Soft delete an entry to trash. - Publish (
publish): Promote draft changes to live version. - Unpublish (
unpublish): Revert published live entry to draft. - Schedule (
schedule): Set a future publication timestamp. - Unschedule (
unschedule): Cancel scheduled publication. - Duplicate (
duplicate): Clone an existing entry into a new draft. - Restore (
restore): Restore a trashed entry. - Permanently Delete (
permanentDelete): Hard delete a trashed entry. - Compare Draft and Live (
compare): Diff draft changes against the live version. - Discard Draft (
discardDraft): Discard pending draft edits and revert to live version. - Get Content Terms (
getContentTerms): Retrieve taxonomy terms assigned to an entry. - Set Content Terms (
setContentTerms): Replace taxonomy term assignments on an entry. - Get Translations (
getTranslations): Retrieve translation variants linked to the same translation group. - Get Authors (
getAuthors): Retrieve distinct authors of content items within a collection. - Get Trashed (
getTrashed): Retrieve soft-deleted content items in a collection with cursor pagination and locale filtering. - Get Edit Lock (
getLock): Check current edit lock status and holder information for a content item. - Acquire Edit Lock (
acquireLock): Acquire or refresh an edit lock lease on a content item. - Release Edit Lock (
releaseLock): Release the caller’s edit lock lease on a content item.
Media (15 operations)
- Get Many (
getAll): List media files with cursor pagination, MIME type, folder filtering, and case-insensitive filename substring search (q). Note:includeUsageprovides a coverage-aware usage summary;usage.countisnullunless the caller holds both the RBACcontent:read_draftspermission andadmintoken scope (use Get Usage for complete usage references). - Get (
get): Get metadata for a media file by ID. Note:includeUsageprovides a coverage-aware usage summary (usage.countisnullunless caller holds both the RBACcontent:read_draftspermission andadmintoken scope). - Upload (
upload): Upload binary files directly via multipart form data, with optionalfieldIdallowlist targeting, pixel dimensions (width,height), and LQIP placeholder thumbnail (thumbnailBinaryPropertyName). - Replace Image (
replaceImage): Replace the binary file of an existing image (image/jpeg,image/png, orimage/webp) while preserving its ID, filename, and storage identity. Updates bytes, size, dimensions, and content hash, while invalidating and explicitly resettingblurhash,dominantColor, andfocalX/focalYtonull(does not regenerate derived metadata). Requires positive integerwidthandheight. - Get Upload Target (
getUploadTarget): Initiate a staged upload workflow by requesting a pre-signed or direct upload destination for a pending file (filename,contentType,size). When deduplication (deduplicate: true) is enabled and a matching checksum is found, the endpoint short-circuits the upload and immediately returns{ existing: true, mediaId, storageKey, url }. - Upload Pending File (
uploadPending): Upload raw binary data directly to the staged upload URL / pending media endpoint (PUT /media/{id}/upload) using raw binary streaming (Content-Type,Content-Length) rather than multipart form data. - Confirm Upload (
confirmUpload): Finalize a staged media upload (POST /media/{id}/confirm) after binary data has been written, optionally recording validatedsize,width, andheight. - Update Metadata (
update): Update media title, alt text, caption, focal points (focalXandfocalYmust be provided together between 0.0 and 1.0, or cleared viaclearFocalPoint/null), positive integer dimensions, or folder (use "unfiled" or empty string to unfile). - Delete (
delete): Delete a media record and associated storage file. - Get Usage (
getUsage): Retrieve content entries and site settings referencing a media file with cursor pagination (cursor,limit). Requires PAT scopeadminand RBACmedia:read+content:read_drafts. - Get Many Folders (
getAllFolders): List media folders. - Get Folder (
getFolder): Get single media folder metadata by ID. - Create Folder (
createFolder): Create a new folder to organize media assets. - Update Folder (
updateFolder): Update media folder name. - Delete Folder (
deleteFolder): Delete a media folder (unfiles referencing media items by settingfolder_idto null; does not require the folder to be empty).
Menu (9 operations)
- Get Many (
getAll): Retrieve all navigation menus with optional locale filtering. - Get (
get): Retrieve a single menu and its navigation item hierarchy by menu name with optional locale filtering. - Create (
create): Create a new navigation menu with name and label; optionally configure target locale or translate an existing menu (translationOf). - Update (
update): Update a menu label with optional locale filtering. - Delete (
delete): Permanently delete a menu and all its navigation items for the targeted menu and locale (does not delete referenced content). - Create Item (
createItem): Add a navigation item to a menu (custom,page,post,taxonomy, orcollection) with optional parent, ordering, target, and styling. - Update Item (
updateItem): Update navigation item label, URL, target, attributes, parent, or sort order (supports explicit null to move items to root). - Delete Item (
deleteItem): Remove a navigation item from a menu (does not delete referenced content). - Reorder Items (
reorderItems): Atomically update menu hierarchy and sibling ordering via an array of item IDs, parent references, and sort positions.
Redirect (9 operations)
- Get Many (
getAllRedirects): List URL redirect rules with cursor pagination and search, group, enabled, auto filters. - Get (
getRedirect): Retrieve redirect rule by ID. - Create (
createRedirect): Create a redirect rule (301,302,307,308,410,451). - Update (
updateRedirect): Update redirect rule source, destination, status code, enabled state, or group. - Delete (
deleteRedirect): Delete a redirect rule by ID. - Get 404 Entries (
get404Entries): Retrieve recorded 404 Not Found error entries with cursor pagination and search filter. - Get 404 Summary (
get404Summary): Retrieve aggregation summary of top 404 error paths. - Prune 404 Log (
prune404Log): Delete 404 error log entries older than an ISO 8601 datetime threshold. - Clear All 404 Entries (
clear404Log): Destructively delete all recorded 404 log entries.
Schema (12 operations)
- Get Many Collections (
getCollections): Retrieve all collections defined in the schema. - Get Collection (
getCollection): Retrieve a single collection schema by slug, optionally including its field definitions (includeFields). - Create Collection (
createCollection): Register a new collection schema with slug, label, and optional metadata (supports,admin,source,urlPattern,routable,hasSeo,hidden,sortOrder,editLocking,group). Server defaults forsupportsare preserved when omitted. - Update Collection (
updateCollection): Update collection schema label, metadata, comments moderation, or title/date field bindings (rejects empty updates). UsesortOrder(integer) to update sidebar position, or enableclearSortOrder: true(or passsortOrder: null) to clear explicit sidebar position and revert to default alphabetical ordering (note thatsortOrderandclearSortOrderare mutually exclusive). - Delete Collection (
deleteCollection): Permanently deletes the collection schema and drops its underlying content table. Relations involving the collection are also removed, which cascades to bound reference fields on other collections. When content exists, deletion fails unlessforce=trueis explicitly provided. - Reorder Collections (
reorderCollections): Update admin sidebar display order of collections via an array of collection slugs. Listed collections receive explicit positions 0..N; omitted collections have explicit order cleared and sort alphabetically. Rejects unknown or duplicate slugs. - Get Many Fields (
getFields): Retrieve all field definitions for a collection schema. - Get Field (
getField): Retrieve a single field schema by slug within a collection. - Create Field (
createField): Add a new field definition to a collection schema across 17 supported field types (string,text,url,number,integer,boolean,datetime,select,multiSelect,portableText,image,file,reference,json,slug,repeater,blocks). Field constraints (validation) and widget rendering options (options) are passed as flexible JSON objects. For new reference fields, specifytargetCollectionin the validation JSON (e.g.{ "targetCollection": "authors" }). Referenced block types must already exist in EmDash. - Update Field (
updateField): Update an existing field schema's label, type, options, widget, or validation rules (rejects empty updates). Passing empty string""clears the widget (JSONnullis rejected upstream by the EmDash schema withVALIDATION_ERROR). Note that target collection on an active reference field is immutable. Upstream enforces strict migration restrictions: mutatingrequired,unique, or settingtranslatable: falserequires manual content migration and is rejected upstream withFIELD_UPDATE_REQUIRES_MIGRATION; type changes across SQL column affinities are rejected withFIELD_TYPE_COLUMN_CHANGE(compatible text-alias transitions such astexttostringor no-op reassertions succeed). - Delete Field (
deleteField): Permanently deletes the field and drops its column from the content table. WhendeleteRelation=trueis enabled on a reference field, it also cascades to delete the underlying relationship, all relation edges, and the field bound to the opposite side of the relation on the other collection. - Reorder Fields (
reorderFields): Update field display ordering within a collection via an array of field slugs. Upstream updates each supplied field slug sequentially; partial field lists update only listed fields while omitted fields retain existing sort orders (which may cause position collisions); unmatched or unknown field slugs silently update 0 rows without error (returns 200, unlikereorderCollectionswhich returns 404); duplicate slugs are rejected locally; provide the complete field list for deterministic ordering.
Caution on Schema Mutations:
- Collection Deletion: Dropping a collection is irreversible and removes the backing SQLite table and all content entries. Always test with disposable collections.
- Reference Field Cascade: Deleting a reference field with
deleteRelation=truecascades across collection boundaries, modifying the schema of the related collection by removing the reciprocal field.
Search (5 operations)
- Search (
search): Full-text search across indexed content with cursor pagination, collections filter, locale, status, and scope (allortitle). - Suggest (
suggest): Autocompletion prefix suggestions with collection and locale filters. - Get Stats (
getStats): Retrieve search index statistics and document counts. - Rebuild Index (
rebuildIndex): Trigger a search index rebuild for a specific collection. - Enable / Configure Search (
enableSearch): Configure SQLite FTS5 search indexing for a collection, including tokenizer strategies (porter unicode61,unicode61,trigram) and column weight mapping.
Section (5 operations)
- Get Many (
getAll): Retrieve sections with cursor pagination and optional source (theme,user,import) or search filters. - Get (
get): Retrieve a single section by slug. - Create (
create): Create a new section with slug, title, structured JSON content, and optional description, keywords, preview media ID, source (userorimport), or theme ID. - Update (
update): Update section slug, title, description, keywords, structured JSON content, or preview media ID (pass null or empty string to clear preview media). - Delete (
delete): Delete a custom or imported section (theme-defined sections are protected and cannot be deleted).
Settings (2 operations)
- Get (
get): Retrieve current site settings object directly from the CMS without static schema constraints. - Update (
update): Update site settings with a validated JSON object or expression viaPOST /settings(merges updates with existing settings; unspecified settings remain unchanged).
Taxonomy (10 operations)
- Get Many (
getAllTaxonomies): List all registered taxonomies. - Get (
getTaxonomy): Retrieve taxonomy schema and metadata. - Update (
updateTaxonomy): Update taxonomy schema (label,labelSingular,hierarchical,collections). - Delete (
deleteTaxonomy): Delete taxonomy definition and its terms. - Get Many Terms (
getAllTerms): List terms within a taxonomy. - Get Term (
getTerm): Retrieve single taxonomy term by slug. - Create Term (
createTerm): Create a new term with label, slug, description, parent, and locale. - Update Term (
updateTerm): Update an existing term by slug. - Delete Term (
deleteTerm): Delete a term from a taxonomy. - Reorder Terms (
reorderTerms): Update display ordering of taxonomy terms (POST /taxonomies/{name}/reorder).
Widget Area (8 operations)
- Get Many (
getAll): Retrieve all registered widget areas with their widgets. - Get (
get): Retrieve a widget area by name including its ordered widgets. - Create (
create): Register a new custom widget area with name, label, and optional description. - Delete (
delete): Delete a widget area (cascades deletion to all contained widgets). - Create Widget (
createWidget): Add a widget (contentwith structured content blocks,menuwith menu name, orcomponentwith component ID and JSON properties) to a widget area. - Update Widget (
updateWidget): Update widget type, title, content blocks, menu name, component ID, or component properties. - Delete Widget (
deleteWidget): Remove a widget from a widget area (does not delete referenced content, menus, or components). - Reorder Widgets (
reorderWidgets): Update display ordering of widgets in an area using an ordered array of widget IDs.
Existing trigger workflows
Version 0.1.4 removes the EmDash webhook trigger because the EmDash webhook notifier plugin is currently broken and its event delivery cannot be verified. After upgrading, existing workflows that contain emdashTrigger will have a missing node and must be migrated before they can run. Replace it with Schedule Trigger and EmDash actions to poll for changes, or use another independently supported event source.
Usage
Declarative architecture
This integration relies on declarative routing throughout the node definition. Binary uploads use preSend hooks to construct multipart form payloads directly in memory, and response envelopes use postReceive hooks to unwrap API payloads. Any irregular or nested API structures (such as generic "weird JSON" payloads) are addressed declaratively with JMESPath or parameter expressions rather than requiring programmatic execution.
Dynamic collection discovery
Collection, folder, and taxonomy fields use n8n resource locators. You can select items interactively from a live EmDash instance or toggle to manual mode to provide dynamic expressions or IDs from upstream workflow nodes.
Cursor pagination
List operations support EmDash opaque cursor pagination. Set Return All to true to fetch all available records automatically, or disable it and specify a custom Limit.
Staged and Direct Media Upload Workflows
EmDash CMS supports both single-step direct uploads and multi-step staged uploads:
Direct Upload (
upload):- Upload binary assets directly in one request via multipart form data (
POST /media). - Supports optional folder placement (
folderId), duplicate checksum matching (deduplicate: true), automatic filename collision avoidance (ensureUniqueFilename: true), field allowlist enforcement (fieldId), explicit image dimensions (width,height), and downscaled thumbnail binary attachments (thumbnailBinaryPropertyName) for low-quality image placeholder (LQIP) generation.
- Upload binary assets directly in one request via multipart form data (
Staged Upload Workflow (
getUploadTarget→uploadPending→confirmUpload):- Recommended for large files, streaming pipelines, or decoupled architectures.
- Step 1: Get Upload Target (
POST /media/upload-url):- Registers a pending upload with
filename, MIMEcontentType, and filesizein bytes (must be an integer $\ge 0$). - Optional fields include
contentHash,fieldId,deduplicate,ensureUniqueFilename, andfolderId(passing'unfiled'or empty string places the item at root). - Deduplication short-circuit: When
deduplicate: trueis enabled and a matching checksum is detected, the EmDash API short-circuits the upload flow and immediately returns the existing media asset:
In this case, downstream Upload Pending File and Confirm Upload steps must be skipped.{ "existing": true, "mediaId": "...", "storageKey": "...", "url": "..." }
- Registers a pending upload with
- Step 2: Upload Pending File (
PUT /media/{id}/upload):- Writes the raw file binary buffer directly to the pending media endpoint using raw binary streaming (
Content-TypeandContent-Lengthheaders). Unlike direct upload, this does not wrap data in multipart form boundaries, maximizing throughput and minimizing memory overhead.
- Writes the raw file binary buffer directly to the pending media endpoint using raw binary streaming (
- Step 3: Confirm Upload (
POST /media/{id}/confirm):- Finalizes the pending upload and transitions the asset to
readystate. - Optionally supplies verified
size($\ge 0$),width($> 0$), andheight($> 0$) dimensions. Unconfigured dimensions are not defaulted to 0.
- Finalizes the pending upload and transitions the asset to
Image Replacement (
replaceImage):- The
PUT /media/{id}/replaceendpoint replaces the binary file of an existing image asset (image/jpeg,image/png, orimage/webp). - Preserves the existing media record's ID, filename, creation timestamp, and storage key / URL identity while updating file size, width, height, and content hash.
- Image replacement does NOT regenerate derived image metadata: upstream explicitly invalidates and resets
blurhashtonull,dominantColortonull,focalXtonull, andfocalYtonull. - Requires positive integer
widthandheightparameters. Replacement MIME type must exactly match the original item.
- The
Media Usage Reference Inspection (
getUsage):- Querying referencing content entries and site settings requires Personal Access Token scope
admin(notmedia:read) alongside RBAC capabilitiesmedia:readandcontent:read_drafts. - Supports cursor pagination via
cursorandlimit(1–100, default 50). - Preserves the complete response payload (
items,nextCursor,siteSettings,coverage) without auto-flattening or stripping. - In Get Many (
getAll) and Get (get), theincludeUsagetoggle attaches an inline usage summary; however,usage.countremainsnullunless the caller possesses both the RBACcontent:read_draftspermission and theadmintoken scope (amedia:readPAT alone cannot expose draft-derived usage counts). Dedicated media reference inspection via Get Usage (GET /media/{id}/usage) separately requires PAT scopeadmin, RBACmedia:read, and RBACcontent:read_drafts.
- Querying referencing content entries and site settings requires Personal Access Token scope
Collaborative edit locks and concurrency control
EmDash provides dual-layer write protection to prevent conflicting edits in multi-user editorial environments:
- Collaborative edit locks:
- Edit locks coordinate active editing sessions between users and automated workflows to prevent accidental overwrites during active authoring.
- Locks currently use a 7-minute lease in EmDash 1.0.1 and expire automatically unless refreshed. Calling Content → Acquire Edit Lock on an item already locked by the caller refreshes this lease duration.
- Session tokens (
token): Specify an optional caller session token (up to 128 characters) when acquiring an edit lock. When releasing the lock via Content → Release Edit Lock, supplying the same token ensures that one workflow session does not inadvertently release a lock another session still relies on. - Takeover risk (
takeover: true): Callers must already be authorized to edit the entry (owned content may be authorized throughcontent:edit_own, while other content requirescontent:edit_any). Once authorized, enablingtakeover: trueallows the caller to replace the active lock holder. Use this with caution: breaking an active lease will disrupt the current editor's in-flight work.
- Relationship between edit locks and
_rev:- Edit locks coordinate collaborative presence and in-flight sessions;
_revrevision tokens provide optimistic concurrency control at write/commit time. - Neither replaces the other: holding an edit lock does not eliminate the need for
_revchecks during updates, and supplying_revdoes not bypass an edit lock held by another editor unlessoverrideLock: trueis explicitly provided. Workflows should use edit locks to coordinate long-running editorial tasks and pass_revto guarantee data integrity against stale writes.
- Edit locks coordinate collaborative presence and in-flight sessions;
Author discovery and privacy
The Content → Get Authors operation returns distinct author records for a collection, including author name, user ID, email address, and avatar URL. Workflows that process or forward author information to notifications, external integrations, or analytics platforms must handle these records responsibly and comply with applicable privacy standards (such as GDPR or internal data handling policies).
Comment moderation and privacy
Comment records returned by moderation endpoints contain commenter personal information, including author email (authorEmail) and cryptographic IP hash (ipHash). Workflows that process or forward comment outputs to notification channels, logs, or external systems should handle and redact these fields appropriately in accordance with organizational privacy standards.
Automated comment moderation workflows
To automate comment moderation workflows (such as AI content analysis, automated spam detection, or alerts), configure an n8n workflow using the Schedule Trigger node to periodically poll Comment → Get Many filtered by status: pending.
Menu management and hierarchy semantics
The Menu resource enables full lifecycle management of EmDash navigation structures, supporting multi-level hierarchies, localized menu variants, and referenced or custom navigation links:
- Token scope and RBAC: EmDash enforces two distinct authorization layers:
- Personal Access Token (PAT) Scopes:
- Menu reads (
GET): requirescontent:read - Menu writes (
POST,PUT,DELETE): requiresmenus:manage(orcontent:write, which implicitly grantsmenus:manage, oradmin) - Caution: Do NOT configure invented PAT scopes such as
menus:read,menu:read, ormenu:write— they do not exist in EmDash's token system.
- Menu reads (
- Underlying User RBAC Permissions:
- Menu reads: user must have
menus:readrole capability - Menu writes: user must have
menus:managerole capability (Editor or Administrator)
- Menu reads: user must have
- Personal Access Token (PAT) Scopes:
- Menu translations: When creating a translated menu variant, configure
translationOfwith the canonical menu ID and specify the targetlocalecode. The menunamemust match the canonical menu name. EmDash clones existing navigation items into the new menu and joins it to the canonical translation group. - Custom URL safety: Navigation items configured with
type: customvalidate URLs through EmDash's upstreamsafeHrefsanitizer. Permitted URL schemes includehttp,https,mailto,tel, relative web paths (/about), and fragment identifiers (#contact). Potentially unsafe protocols (such asjavascript:ordata:) are rejected. - Referenced content semantics: Navigation items linking to CMS entries (
page,post,taxonomy, orcollection) requirereferenceCollection(the target collection slug) andreferenceId. In EmDash,referenceIdcorresponds to the translation-group identifier of the referenced content rather than an individual revision ID, allowing navigation links to resolve to the appropriate language variant automatically. - Hierarchy and ordering: The
reorderItemsoperation accepts a JSON or native expression list of{ id, parentId, sortOrder }objects. SettingparentIdto a sibling item ID creates nested sub-menus, whilenullpositions items at the root level.sortOrderdefines a zero-based integer display sequence among siblings. When updating single items viaupdateItem, passing an empty string or literal"null"moves an item back to the root level, whereas omittingparentIdpreserves existing hierarchy. - Menu webhooks: Workflows responding to navigation changes should be scheduled periodically or sequenced downstream of content publishing flows.
Example: Automated campaign navigation update
A common content automation scenario involves publishing a promotional landing page and immediately integrating it into the site navigation menu:
- Trigger on Publish: A Schedule Trigger with EmDash actions detects a newly published landing page in the
pagescollection (e.g.translationGroupId: "grp_summer_sale"). - Add Navigation Item: An EmDash node executes Menu → Create Item:
- Menu:
main-navigation - Type:
Page - Label:
Summer Sale - Reference Collection:
pages - Reference ID:
={{ $json.translationGroupId }} - Additional Fields → Target:
_self
- Menu:
- Reorder Menu: A subsequent EmDash node executes Menu → Reorder Items to place the new campaign link prominently at the front of the top-level navigation (
sortOrder: 0).
Settings Management
The Settings resource provides direct access to site-wide configuration stored in EmDash CMS:
- Get Settings (
get): Fetches the full settings object. The response envelope is automatically unwrapped to return the raw settings data. - Update Settings (
update): Updates site settings by sending a validated JSON payload viaPOST /settings. - Merge semantics: EmDash merges submitted settings with existing configuration; unspecified fields remain untouched, so workflows can submit partial settings objects containing only the targeted updates.
- Dynamic JSON input and schema behavior: The n8n node parameter accepts a flexible JSON object or expression for forward compatibility. Note that current upstream EmDash 1.0.1 parses update payloads with a finite Zod schema (
settingsUpdateBody) that strips unknown properties; arbitrary custom keys are not persisted by EmDash 1.0.1, though future CMS releases may accept additional fields without requiring node UI changes. - Best practices: While partial updates do not overwrite omitted settings, calling Get Settings first can be useful when reviewing current values or computing dynamic property updates. Backups or exporting settings prior to broad configuration changes are always recommended.
- Authentication and permissions:
- Personal Access Token (PAT) Scopes: Reading settings via
Getrequiressettings:read(oradmin). Modifying settings viaUpdaterequiressettings:manage(oradmin). - RBAC Capabilities: The authenticated user account must possess the corresponding internal RBAC permission (
settings:readcapability for reads;settings:managecapability, typical of the Administrator role, for updates).
- Personal Access Token (PAT) Scopes: Reading settings via
Section Management
The Section resource provides full lifecycle management of reusable template and layout sections within EmDash CMS:
- Structured Content Blocks: Section content is structured JSON representing component and layout blocks (such as block definitions, settings, and nested layouts). The node validates content via
validateStructuredContentbefore dispatch to ensure a valid JSON object or array structure. - Source Constraints and Protection: Sections can be created with source
userorimport. EmDash strictly rejects creating sections withsource: "theme"(HTTP 400 Bad Request), as theme sections are defined in codebase templates. Furthermore, theme-defined sections are protected and cannot be deleted via the API (EmDash returns HTTP 403 Forbidden). - Preview Media Semantics: The optional
previewMediaIdlinks a media library asset to the section to provide visual thumbnails in page and layout builders. In Update Section, passing an explicitnull, literal"null", or empty string""clears the existing preview media association. Non-string, non-null values (such as numbers, booleans, arrays, or objects) are strictly rejected with a validation error. - Dynamic Section Discovery: The section resource locator uses
getSectionslistSearch, which queriesGET /sectionswithlimit=100and passes the interactive search term to the upstreamsearchquery parameter, with client-side fallback formatting. - Authentication and Permissions:
- PAT Scopes: Section reads (
GET) requirecontent:read. Section mutations (POST,PUT,DELETE) requirecontent:write(oradmin). EmDash does not define separatesections:*PAT scopes. - RBAC Capabilities: The authenticated user must separately possess the
sections:readrole capability for reads, andsections:managecapability (Editor or Administrator) for mutations.
- PAT Scopes: Section reads (
- Webhooks: Workflows managing sections should be scheduled or triggered downstream of content workflows.
Widget Area and Widget Configuration
The Widget Area resource manages theme-registered and custom widget zones and the widgets placed inside them:
- Widget Types: Widgets support three distinct types:
content: Renders structured content blocks configured via thecontentJSON array.menu: Renders an existing navigation menu specified bymenuName.component: Renders a site or theme component specified bycomponentId, with customizable options incomponentPropsJSON object.
- Cascade Deletion: Deleting a widget area (
DELETE /widget-areas/{name}) permanently cascades deletion to all contained widgets in the database. - Widget Deletion Scope: Deleting an individual widget (
DELETE /widget-areas/{name}/widgets/{id}) removes the widget from the area without deleting the parent widget area, and without deleting referenced menus, components, or content items. - Widget Update Clearing Semantics: In Update Widget, passing an empty string
""clearstitle,menuName, orcomponentId(upstream schema accepts strings, and the route handler converts empty strings""toNULLin the database). Omitted fields are not included in the payload, preserving existing values. Forcontent, an empty array[]is preserved, and forcomponentProps, an empty object{}is preserved. Changing widgettypedoes not implicitly send or clear fields from the previous type unless explicitly supplied. - Widget Reordering Semantics: The
reorderWidgetsoperation accepts an array or comma-separated list of widget IDs (widgetIds). EmDash accepts a partial widget ID list, but only supplied widgets receive new zero-based sort positions; for deterministic ordering, provide the complete ordered list of widgets in the area. - Timestamp Conventions: Upstream EmDash
widgetAreaSchemareturns snake_case timestamps (created_atandupdated_at), differing from the camelCase conventions used by content and comments. - Update Safety: Upstream EmDash requires at least one field to update on
PUT /widget-areas/{name}/widgets/{id}; omitting all update fields returns HTTP 400 ("No fields to update"). The node validates this preSend to avoid unnecessary network roundtrips. - Pagination: The
GET /widget-areasendpoint returns all registered widget areas in{ items: [...] }without cursor pagination. - Authentication and Permissions:
- PAT Scopes: Widget area reads (
GET) requirecontent:read. Widget area and widget mutations (POST,PUT,DELETE) requirecontent:write(oradmin). EmDash does not define separatewidgets:*PAT scopes. - RBAC Capabilities: The authenticated user must separately possess the
widgets:readrole capability for reads, andwidgets:managecapability (Editor or Administrator) for mutations.
- PAT Scopes: Widget area reads (
Troubleshooting
For local development, run npm run dev -- --custom-user-folder /tmp/n8n-node-run and openhttp://localhost:5690 manually. The pinned CLI browser shortcut can open port 5678 instead. If 5690
is occupied, useN8N_PORT=5692 npm exec -- n8n-node dev --custom-user-folder /tmp/n8n-node-run and open port 5692.
- Token permissions: Ensure your Personal Access Token includes the required scopes for the operations invoked. Operations that modify system settings (such as index rebuilds, search enablement, or redirect/404 management) require the
adminscope. - Base URL and routing: Enter the bare root URL of your EmDash installation (for example,
https://cms.example.com). The node automatically normalizes trailing slashes and prefixes paths with/_emdash/api. - Concurrent edits: If an update fails with an
ENTRY_LOCKEDor revision mismatch error, fetch the latest content item revision using Get to obtain the current_revtoken before retrying. - Report defects: File reproducible bug reports on GitHub Issues without including credentials or sensitive tokens.
Resources
- Black Swamp AI package page
- n8n community nodes documentation
- EmDash Documentation
- Changelog
- API Matrix
- Testing Documentation
- Branding Guide