REST-API-Referenz

Auf dieser Seite

EmDash stellt seine unterstützte Anwendungsprogrammierschnittstelle (API) unter /_emdash/api/ bereit. Verwenden Sie das generierte OpenAPI-3.1-Dokument für Anfrageparameter, Bodies, Antwortschemas, Statuscodes und Client-Generierung:

GET /_emdash/api/openapi.json

Das Dokument wird aus denselben Zod-Schemas erzeugt, die die API verwendet. Es spiegelt auch die konfigurierte maximale Medien-Upload-Größe wider.

Grenze des öffentlichen Vertrags

Das OpenAPI-Dokument ist die Grenze der unterstützten REST-API. EmDash hat außerdem Routen für die Admin-Oberfläche und Protokoll-Workflows. Eine Route, die im Quellcode existiert, aber in OpenAPI fehlt, ist für externe Clients keine unterstützte REST-Operation.

Diese Unterscheidung gilt für Backup-, Byline-Verwaltungs-, Relations-Traversal-, Plugin-Verwaltungs-, Setup-, Import- und Authentifizierungsrouten. Verwenden Sie den Backup-Leitfaden für Backups und die MCP-Byline-Tools für unterstützte Byline-Verwaltung. OAuth-Endpunkte sind Protokoll-Endpunkte; ermitteln Sie sie über die Metadaten im Abschnitt MCP OAuth, anstatt sie als Anwendungs-REST-Endpunkte zu behandeln.

Authentifizierung und Autorisierung

Die meisten Operationen akzeptieren entweder ein EmDash-Session-Cookie oder ein Bearer-Token. Senden Sie ein Personal Access Token oder OAuth Access Token im Header Authorization:

Authorization: Bearer $EMDASH_TOKEN

Bearer-Tokens sind durch ihre Scopes und die Rolle des zugehörigen Benutzers begrenzt. Session-Anfragen verwenden die Rolle des Benutzers. Siehe Benutzerrollen und Token-Scopes für das Autorisierungsmodell.

GET und POST /_emdash/api/comments/{collection}/{contentId} sind öffentlich. Die GET-Operation liefert genehmigte Kommentare; die POST-Operation reicht einen Kommentar zur Moderation ein. Die übrigen Kommentar-Moderationsoperationen erfordern Authentifizierung.

Schutz vor Cross-Site-Request-Forgery

Für eine zustandsändernde Anfrage, die über ein Session-Cookie authentifiziert ist, fügen Sie diesen Header hinzu:

X-EmDash-Request: 1

Bearer-Token-Anfragen benötigen den Header nicht, weil sie keine impliziten Browser-Anmeldedaten verwenden. Browser-Anfragen an eine öffentliche Schreiboperation müssen entweder den Header senden oder einen Origin haben, der mit der öffentlichen oder Anfrage-Origin der EmDash-Site übereinstimmt.

Antwort-Envelopes

Eine erfolgreiche JSON-Antwort setzt success auf true und legt das operationsspezifische Ergebnis in data ab:

{
	"success": true,
	"data": {
		"items": []
	}
}

Bei einem Fehler ist success false und es gibt einen stabilen maschinenlesbaren Code sowie eine Nachricht. Einige Fehler enthalten auch strukturierte details:

{
	"success": false,
	"error": {
		"code": "NOT_FOUND",
		"message": "Content item not found"
	}
}

Verwenden Sie die Statuscodes und Fehlerschemas jeder OpenAPI-Operation. Häufige Status sind 400 bei ungültiger Eingabe, 401 bei fehlenden oder ungültigen Anmeldedaten, 403 bei unzureichendem Scope oder fehlender Berechtigung, 404 bei fehlender Ressource, 409 bei Zustandskonflikt, 413 bei zu großem Upload, 422 wenn ein Plugin das Speichern ablehnt, und 500 bei internem Fehler.

Endpunktinventar

Die Operations-ID ist im generierten Vertrag stabil und wird von OpenAPI-Client-Generatoren häufig als Methodenname verwendet. Das folgende Inventar wird gegen das generierte OpenAPI-Dokument geprüft.

Inhalt

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/content/{collection}listContentList content items
POST/_emdash/api/content/{collection}createContentCreate a content item
GET/_emdash/api/content/{collection}/{id}getContentGet a content item
PUT/_emdash/api/content/{collection}/{id}updateContentUpdate a content item
DELETE/_emdash/api/content/{collection}/{id}deleteContentDelete a content item (soft delete)
POST/_emdash/api/content/{collection}/{id}/publishpublishContentPublish a content item
POST/_emdash/api/content/{collection}/{id}/unpublishunpublishContentUnpublish a content item
POST/_emdash/api/content/{collection}/{id}/schedulescheduleContentSchedule content for future publishing
DELETE/_emdash/api/content/{collection}/{id}/scheduleunscheduleContentCancel scheduled publishing
POST/_emdash/api/content/{collection}/{id}/duplicateduplicateContentDuplicate a content item
POST/_emdash/api/content/{collection}/{id}/restorerestoreContentRestore a content item from trash
DELETE/_emdash/api/content/{collection}/{id}/permanentpermanentDeleteContentPermanently delete a content item
GET/_emdash/api/content/{collection}/{id}/comparecompareContentCompare live and draft revisions
POST/_emdash/api/content/{collection}/{id}/discard-draftdiscardDraftDiscard draft changes
GET/_emdash/api/content/{collection}/{id}/lockgetEntryLockRead the entry’s edit lock
POST/_emdash/api/content/{collection}/{id}/lockacquireEntryLockTake or refresh the entry’s edit lock
DELETE/_emdash/api/content/{collection}/{id}/lockreleaseEntryLockRelease the caller’s edit lock
GET/_emdash/api/content/{collection}/{id}/translationsgetContentTranslationsGet translations for a content item
GET/_emdash/api/content/{collection}/{id}/terms/{taxonomy}getContentTermsGet taxonomy terms assigned to a content item
POST/_emdash/api/content/{collection}/{id}/terms/{taxonomy}setContentTermsSet taxonomy terms on a content item
GET/_emdash/api/content/{collection}/authorslistContentAuthorsList distinct authors of a collection’s content
GET/_emdash/api/content/{collection}/trashlistTrashedContentList trashed content items

Medien

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/medialistMediaList media items
POST/_emdash/api/mediauploadMediaUpload a media item
GET/_emdash/api/media/folderslistMediaFoldersList media folders
POST/_emdash/api/media/folderscreateMediaFolderCreate a media folder
GET/_emdash/api/media/folders/{id}getMediaFolderGet a media folder
PUT/_emdash/api/media/folders/{id}updateMediaFolderUpdate a media folder
DELETE/_emdash/api/media/folders/{id}deleteMediaFolderDelete a media folder
GET/_emdash/api/media/{id}getMediaGet a media item
PUT/_emdash/api/media/{id}updateMediaUpdate media metadata
DELETE/_emdash/api/media/{id}deleteMediaDelete a media item
GET/_emdash/api/media/{id}/usagegetMediaUsageGet media usage details
PUT/_emdash/api/media/{id}/replacereplaceMediaImageReplace a media image
POST/_emdash/api/admin/media-usage/repairrepairMediaUsageRepair media usage indexes
GET/_emdash/api/admin/media-usage/progressgetMediaUsageProgressGet media usage indexing progress
POST/_emdash/api/admin/media-usage/progressadvanceMediaUsageProgressAdvance media usage indexing
GET/_emdash/api/admin/media-usage/worklistMediaUsageWorkList durable media usage work
GET/_emdash/api/admin/media-usage/activationgetMediaUsageActivationGet media usage activation status
POST/_emdash/api/admin/media-usage/activationadvanceMediaUsageActivationAdvance media usage activation
POST/_emdash/api/admin/media-usage/work/retryretryMediaUsageWorkRetry one durable media usage job
GET/_emdash/api/admin/media-usage/collection-deletionslistMediaUsageCollectionDeletionsList durable collection deletions
POST/_emdash/api/admin/media-usage/collection-deletions/retryretryMediaUsageCollectionDeletionRetry one collection deletion
POST/_emdash/api/media/upload-urlgetMediaUploadUrlGet a media upload target
POST/_emdash/api/media/{id}/confirmconfirmMediaUploadConfirm a media upload
PUT/_emdash/api/media/{id}/uploaduploadPendingMediaUpload a pending media file through EmDash

Schema

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/schema/block-typeslistBlockTypesList block types
POST/_emdash/api/schema/block-typescreateBlockTypeCreate a block type
GET/_emdash/api/schema/block-types/{slug}getBlockTypeGet a block type
PUT/_emdash/api/schema/block-types/{slug}updateBlockTypeUpdate a block type
POST/_emdash/api/schema/block-types/{slug}/versions/{version}/activateactivateBlockTypeVersionActivate a block type version
GET/_emdash/api/schema/collectionslistCollectionsList all collections
POST/_emdash/api/schema/collectionscreateCollectionCreate a collection
GET/_emdash/api/schema/collections/{slug}getCollectionGet a collection
PUT/_emdash/api/schema/collections/{slug}updateCollectionUpdate a collection
DELETE/_emdash/api/schema/collections/{slug}deleteCollectionDelete a collection
GET/_emdash/api/schema/collections/{slug}/fieldslistFieldsList fields for a collection
POST/_emdash/api/schema/collections/{slug}/fieldscreateFieldCreate a field
GET/_emdash/api/schema/collections/{slug}/fields/{fieldSlug}getFieldGet a field
PUT/_emdash/api/schema/collections/{slug}/fields/{fieldSlug}updateFieldUpdate a field
DELETE/_emdash/api/schema/collections/{slug}/fields/{fieldSlug}deleteFieldDelete a field
POST/_emdash/api/schema/collections/reorderreorderCollectionsReorder collections in the admin sidebar
POST/_emdash/api/schema/collections/{slug}/fields/reorderreorderFieldsReorder fields in a collection
GET/_emdash/api/schema/orphanslistOrphanedTablesList orphaned content tables
POST/_emdash/api/schema/orphans/{slug}registerOrphanedTableRegister an orphaned table as a collection

Kommentare

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/comments/{collection}/{contentId}listPublicCommentsList approved comments for content
POST/_emdash/api/comments/{collection}/{contentId}createCommentSubmit a new comment
GET/_emdash/api/admin/commentslistAdminCommentsList comments for moderation
GET/_emdash/api/admin/comments/countsgetCommentCountsGet comment status counts
POST/_emdash/api/admin/comments/bulkbulkCommentActionBulk approve, spam, trash, or delete comments
GET/_emdash/api/admin/comments/{id}getCommentGet a single comment
DELETE/_emdash/api/admin/comments/{id}deleteCommentPermanently delete a comment
PUT/_emdash/api/admin/comments/{id}/statusupdateCommentStatusChange comment status

Taxonomien

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/taxonomieslistTaxonomiesList all taxonomy definitions
GET/_emdash/api/taxonomies/{name}getTaxonomyGet a taxonomy definition
PUT/_emdash/api/taxonomies/{name}updateTaxonomyUpdate a taxonomy definition
DELETE/_emdash/api/taxonomies/{name}deleteTaxonomyDelete a taxonomy, its terms, and their content assignments
GET/_emdash/api/taxonomies/{name}/translationslistTaxonomyTranslationsList every locale variant of a taxonomy definition
POST/_emdash/api/taxonomies/{name}/reorderreorderTermsSet the manual order of one sibling group of terms
GET/_emdash/api/taxonomies/{name}/termslistTermsList terms for a taxonomy
POST/_emdash/api/taxonomies/{name}/termscreateTermCreate a term
GET/_emdash/api/taxonomies/{name}/terms/{slug}getTermGet a term by slug
PUT/_emdash/api/taxonomies/{name}/terms/{slug}updateTermUpdate a term
DELETE/_emdash/api/taxonomies/{name}/terms/{slug}deleteTermDelete a term

Menüs

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/menuslistMenusList all menus with item counts
POST/_emdash/api/menuscreateMenuCreate a menu
GET/_emdash/api/menus/{name}getMenuGet a menu with all items
PUT/_emdash/api/menus/{name}updateMenuUpdate a menu
DELETE/_emdash/api/menus/{name}deleteMenuDelete a menu and its items
POST/_emdash/api/menus/{name}/itemscreateMenuItemAdd an item to a menu
PUT/_emdash/api/menus/{name}/items/{id}updateMenuItemUpdate a menu item
DELETE/_emdash/api/menus/{name}/items/{id}deleteMenuItemDelete a menu item
POST/_emdash/api/menus/{name}/reorderreorderMenuItemsBatch reorder menu items

Bereiche

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/sectionslistSectionsList sections
POST/_emdash/api/sectionscreateSectionCreate a section
GET/_emdash/api/sections/{slug}getSectionGet a section by slug
PUT/_emdash/api/sections/{slug}updateSectionUpdate a section
DELETE/_emdash/api/sections/{slug}deleteSectionDelete a section

Widgets

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/widget-areaslistWidgetAreasList all widget areas
POST/_emdash/api/widget-areascreateWidgetAreaCreate a widget area
GET/_emdash/api/widget-areas/{name}getWidgetAreaGet a widget area with widgets
DELETE/_emdash/api/widget-areas/{name}deleteWidgetAreaDelete a widget area and its widgets
POST/_emdash/api/widget-areas/{name}/widgetscreateWidgetAdd a widget to an area
PUT/_emdash/api/widget-areas/{name}/widgets/{id}updateWidgetUpdate a widget
DELETE/_emdash/api/widget-areas/{name}/widgets/{id}deleteWidgetDelete a widget
POST/_emdash/api/widget-areas/{name}/reorderreorderWidgetsReorder widgets in an area

Einstellungen

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/settingsgetSettingsGet site settings
PUT/_emdash/api/settingsupdateSettingsUpdate site settings

Suche

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/searchsearchFull-text search across collections
GET/_emdash/api/search/suggestsearchSuggestAutocomplete search suggestions
POST/_emdash/api/search/rebuildrebuildSearchIndexRebuild the search index for a collection
POST/_emdash/api/search/enableenableSearchEnable or disable search for a collection
GET/_emdash/api/search/statsgetSearchStatsGet search index statistics

Weiterleitungen

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/redirectslistRedirectsList redirects
POST/_emdash/api/redirectscreateRedirectCreate a redirect rule
GET/_emdash/api/redirects/{id}getRedirectGet a redirect
PUT/_emdash/api/redirects/{id}updateRedirectUpdate a redirect
DELETE/_emdash/api/redirects/{id}deleteRedirectDelete a redirect
GET/_emdash/api/redirects/404slistNotFoundEntriesList 404 log entries
POST/_emdash/api/redirects/404spruneNotFoundLogPrune old 404 log entries
DELETE/_emdash/api/redirects/404sclearNotFoundLogClear all 404 log entries
GET/_emdash/api/redirects/404s/summarygetNotFoundSummaryGet 404 summary grouped by path

Benutzer

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/admin/userslistUsersList users
GET/_emdash/api/admin/users/{id}getUserGet user details
PUT/_emdash/api/admin/users/{id}updateUserUpdate a user
POST/_emdash/api/admin/users/{id}/disabledisableUserDisable a user account
POST/_emdash/api/admin/users/{id}/enableenableUserEnable a user account
GET/_emdash/api/admin/allowed-domainslistAllowedDomainsList allowed email domains
POST/_emdash/api/admin/allowed-domainscreateAllowedDomainAdd an allowed email domain
PUT/_emdash/api/admin/allowed-domains/{domain}updateAllowedDomainUpdate an allowed domain
DELETE/_emdash/api/admin/allowed-domains/{domain}deleteAllowedDomainRemove an allowed domain

Transfer

MethodePfadOperationKurzbeschreibung
GET/_emdash/api/admin/transfer/capabilitiesgetTransferCapabilitiesGet site transfer capabilities
GET/_emdash/api/admin/transfer/importslistTransferImportsList site imports
POST/_emdash/api/admin/transfer/importscreateTransferImportCreate a site import
GET/_emdash/api/admin/transfer/imports/{id}getTransferImportGet a site import
GET/_emdash/api/admin/transfer/imports/{id}/missinglistTransferImportMissingFilesList package files still to upload
PUT/_emdash/api/admin/transfer/imports/{id}/files/{path}uploadTransferImportFileUpload one package file
POST/_emdash/api/admin/transfer/imports/{id}/analyzeanalyzeTransferImportAdvance import analysis
GET/_emdash/api/admin/transfer/imports/{id}/plangetTransferImportPlanGet an import plan
POST/_emdash/api/admin/transfer/imports/{id}/cancelcancelTransferImportCancel a site import
POST/_emdash/api/admin/transfer/imports/{id}/abandonabandonTransferImportAbandon a failed or cancelled import
POST/_emdash/api/admin/transfer/imports/{id}/executeexecuteTransferImportStart a planned import
POST/_emdash/api/admin/transfer/imports/{id}/advanceadvanceTransferImportAdvance an executing import
GET/_emdash/api/admin/transfer/imports/{id}/receiptgetTransferImportReceiptGet an import receipt
GET/_emdash/api/admin/transfer/exportslistTransferExportsList site exports
POST/_emdash/api/admin/transfer/exportscreateTransferExportStart a site export
GET/_emdash/api/admin/transfer/exports/{id}getTransferExportGet a site export
POST/_emdash/api/admin/transfer/exports/{id}/advanceadvanceTransferExportAdvance a site export
GET/_emdash/api/admin/transfer/exports/{id}/manifestgetTransferExportManifestDownload an export manifest
GET/_emdash/api/admin/transfer/exports/{id}/files/{path}downloadTransferExportFileDownload one export file
GET/_emdash/api/admin/transfer/exports/{id}/archivedownloadTransferExportArchiveDownload an export archive
GET/_emdash/api/admin/transfer/approvalslistTransferApprovalsList transfer approvals
POST/_emdash/api/admin/transfer/approvals/{id}/approveapproveTransferApprovalApprove a transfer request
POST/_emdash/api/admin/transfer/approvals/{id}/denydenyTransferApprovalDeny a transfer request

Inhaltslebenszyklus und Bylines

Die Referenz zum Inhaltslebenszyklus definiert Zustand, Revision, Berechtigung, Konflikt- und Hook-Verhalten, die REST, MCP, die CLI und das Admin-Panel gemeinsam nutzen.

Inhalts-Lesevorgänge liefern bei Verfügbarkeit ein undurchsichtiges _rev-Token. Senden Sie _rev mit PUT /content/{collection}/{id}, um zu verhindern, dass eine Änderung seit dem Lesevorgang überschrieben wird. Ein veraltetes Token erzeugt einen Konflikt; lesen Sie den Eintrag erneut, bevor Sie es noch einmal versuchen. Die CLI macht diese Prüfung für content update verbindlich, während das REST-Feld für Clients optional bleibt, die bewusst bedingungslos schreiben.

Eintrag lesen und aktualisieren

Lesen Sie den Eintrag, bevor Sie ihn ändern:

GET /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN

Die Antwort enthält Felder, Veröffentlichungszustand und Revisionstoken:

{
	"success": true,
	"data": {
		"item": {
			"id": "01JARTICLE0000000000000000",
			"type": "articles",
			"slug": "launch-notes",
			"status": "published",
			"data": { "title": "Launch notes" }
		},
		"_rev": "opaque-revision-token"
	}
}

Senden Sie nur die Felder, die sich ändern sollen, zusammen mit dem Token aus diesem Lesevorgang:

PUT /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN
Content-Type: application/json

{
	"data": { "title": "Updated launch notes" },
	"_rev": "opaque-revision-token"
}

Das Ändern eines veröffentlichten Eintrags erzeugt einen Entwurf, während die vorherige Version live bleibt. Rufen Sie die Vergleichsoperation auf, um beide Versionen zu prüfen, und veröffentlichen Sie dann den Entwurf oder verwerfen Sie ihn. Das Zurücknehmen der Veröffentlichung behält Inhalt und Veröffentlichungsdatum, hebt ausstehende Planungen auf und entfernt den Eintrag von der Live-Site.

Erstellungs- und Update-Bodies akzeptieren Byline-Credits; Inhaltsantworten enthalten die primäre Byline und geordnete Credits. Die Inhaltsliste kann nach gespeicherten Byline-IDs filtern und optional die abgeleitete Byline eines Autors einbeziehen. Das Erstellen und Verwalten der Byline-Datensätze selbst erfolgt über die MCP-Byline-Tools, nicht über den öffentlichen REST-Vertrag.

Die Lebenszyklusoperationen unterscheiden Soft Delete und dauerhaftes Löschen. Wiederherstellen gibt gelöschten Inhalt als Entwurf ohne Planung zurück; dauerhaftes Löschen entfernt einen Papierkorb-Eintrag und kann nicht rückgängig gemacht werden. Veröffentlichen, Veröffentlichung zurücknehmen, Planen, Planung aufheben, Vergleichen, Entwurf verwerfen und Duplizieren sind getrennte Operationen, damit Clients jeweils einen Zustandsübergang anfordern können.

Bearbeitungssperre für Einträge

Collections können eine siebenminütige Bearbeitungssperre setzen, wenn ein Editor einen Eintrag öffnet. Verwenden Sie die drei Operationen unter /content/{collection}/{id}/lock, um die Sperre zu lesen, zu übernehmen oder zu verlängern und freizugeben.

Eine Lese- oder Acquire-Antwort zeigt, ob Sperren aktiv ist, ob der Aufrufer die Sperre hält und wer sie derzeit hält:

{
	"success": true,
	"data": {
		"enabled": true,
		"heldByCaller": false,
		"holder": {
			"userId": "01JUSER000000000000000000",
			"userName": "Ada",
			"acquiredAt": "2026-05-01T09:12:04.117Z",
			"expiresAt": "2026-05-01T09:19:04.117Z"
		}
	}
}

Ist Bearbeitungssperre für eine Collection deaktiviert, ist enabled false und es wird keine Sperre vergeben. Erneutes Acquire derselben Sperre und Speichern des Eintrags verlängern beide eine Sperre des Aufrufers.

Der Acquire-Body kann ein undurchsichtiges token enthalten, das eine Bearbeitungssitzung identifiziert, und takeover: true, wenn der Benutzer die Sperre eines anderen Editors ersetzen möchte. Übergeben Sie dasselbe Token als Query-Parameter beim Freigeben der Sperre. Ein zweiter Tab desselben Kontos kann dann nicht versehentlich die Sperre des ersten Tabs freigeben.

Hält ein anderer Benutzer die Sperre, liefern geschützte Inhalts-Schreibvorgänge 409 ENTRY_LOCKED. Die Fehlerdetails nennen Inhaber und Ablaufzeit. Um die Sperre zu überschreiben, senden Sie "overrideLock": true im JSON-Body bei Schreibvorgängen mit Body oder ?overrideLock=true bei DELETE ohne Body.

Referenzauswahlen

Ein reference-Feld verknüpft einen Eintrag über eine Relation mit Einträgen in einer anderen Collection. Sein Wert ist nicht Teil von data und ist nach Übersetzungsgruppe keyed, sodass jede Übersetzung eines Eintrags dieselbe Auswahl teilt.

Erstellungs- und Update-Bodies tragen Auswahlen unter references, keyed nach Feld-Slug, jeweils ein Array von höchstens 1000 Eintrags-IDs in Anzeigereihenfolge. EmDash schreibt die Auswahl in derselben Transaktion wie den Eintrag. Das folgende Update ersetzt den Autor des Eintrags:

PUT /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN
Content-Type: application/json

{
	"data": { "title": "Updated launch notes" },
	"references": { "author": ["01JAUTHOR00000000000000000"] },
	"_rev": "opaque-revision-token"
}

Ein Feld, das an das Kind-Ende seiner Relation gebunden ist, wählt Einträge aus, die auf den geschriebenen zeigen; diese haben keine eigene Reihenfolge. Relationslimits gelten an beiden Enden; eine Auswahl, die einem verknüpften Eintrag mehr Eltern gäbe als die Relation erlaubt, wird ebenso abgelehnt wie eine, die selbst zu viele Einträge verknüpft.

Bei einer Collection mit Revisionen wird eine an einem veröffentlichten Eintrag geänderte Auswahl im Entwurf mit den übrigen ausstehenden Änderungen des Eintrags vorgehalten. Sie wird live bei Veröffentlichung und mit dem Entwurf verworfen. Beim Veröffentlichen wird die gesamte Auswahl erneut gegen die Relationslimits geprüft.

Ein Einzel-Lesevorgang liefert references keyed nach Feld-Slug. Jedes Feld enthält die erste Seite verknüpfter Einträge, 50 Stück, mit nextCursor, wenn das Feld mehr enthält, und meldet ID, Slug, Collection, Anzeigetitel, aufgelöste Locale und Übersetzungsgruppe jedes Eintrags. Ein Aufrufer mit Entwurfs-Leserecht sieht eine vorgehaltene Auswahl, wenn der Entwurf eine trägt. Die Inhaltslisten-Operation enthält keine Referenzen.

Relationsdefinitionen und Link-Traversal sind Admin-Routen, fehlen in OpenAPI und liegen außerhalb des öffentlichen Vertrags. Schreiben und lesen Sie Auswahlen über die Inhaltsoperationen oben und rendern Sie sie auf einer Site mit getEmDashEntry() und getEmDashReferences().

Übersetzungen

Der öffentliche REST-Vertrag stellt Inhaltsübersetzungen und Taxonomie-Definitionsübersetzungen bereit. Inhaltserstellung akzeptiert translationOf; Taxonomie-Erstellung nutzt dasselbe Feld für eine Locale-Variante. Die Content-Term-Operationen liefern locale-bewusste Zuweisungen.

GET /taxonomies/{name} liefert bei weggelassenem locale die Definition der Standard-Locale der Site und fällt nur zurück auf den niedrigsten Locale-Code, wenn die Standard-Locale keine Definition hat. Updates verhalten sich anders: ohne locale wird die Definition mit dem niedrigsten Locale-Code geändert. Übergeben Sie locale, damit ein Update einer übersetzten Taxonomie die beabsichtigte Definition trifft. Hat diese Locale keine Definition, liefert das Update NOT_FOUND statt auf eine andere Locale zurückzufallen. Die Translations-Operation liefert jede Definition in der gemeinsamen Gruppe und die von translationOf akzeptierten IDs.

label und labelSingular gehören zur Definition einer Locale. hierarchical und collections gehören zur Taxonomie: jede Locale liefert dieselben Werte, und ein Update, das eines sendet, ändert es für alle Locales. Wird für einen Namen, der in einer anderen Locale existiert, eine Definition erstellt, wird sie dieser Taxonomie hinzugefügt, unabhängig davon, ob die Anfrage translationOf sendet. Die neue Definition übernimmt hierarchical und collections der Taxonomie; ein Create mit abweichenden Werten liefert VALIDATION_ERROR.

Das Löschen einer Taxonomie entfernt jede Locale ihrer Definition, alle Terms und alle Zuweisungen dieser Terms zu Inhalten. Die Inhaltseinträge selbst werden nicht gelöscht.

Die Term-Reorder-Operation ändert eine Geschwistergruppe. Das ids-Array darf nur einen Teil dieser Gruppe enthalten; gelistete Terms tauschen ihre Positionen, ausgelassene bleiben. Beispiel: [A, B, C] mit ids: ["C", "A"] ergibt [C, B, A]. Reordering ändert keine Eltern-Beziehungen; eine Term-Reihenfolge gilt für jede Locale in ihrer Übersetzungsgruppe.

Menü-, Taxonomie-Term- und Byline-Übersetzungsrouten sind nicht im öffentlichen REST-Vertrag. Unterstützte Übersetzungslisten gibt es über menu_translations, taxonomy_term_translations und byline_translations auf dem MCP-Server.

Medien-Endpunkte

Medienoperationen umfassen Auflisten, Upload, Metadaten-Updates, Bildersetzung, Ordner, Nutzungsinformationen und Wartung des Nutzungsindex. Der Medienbibliothek-Leitfaden erklärt den nutzerorientierten Workflow und die Bedeutung der Nutzungsabdeckung.

Medien auflisten und prüfen

GET /media unterstützt Cursor- oder nummerierte Seitenpaginierung, MIME-Typ- und Dateinamenfilter, Ordner und optionale Nutzungszusammenfassungen. Lassen Sie folderId weg, um alle Ordner einzubeziehen, oder setzen Sie folderId=unfiled, um nur die Hauptbibliothek zu erhalten. Setzen Sie includeUsage=1 bei Listen- oder Einzel-Lesevorgängen für Nutzungsinformationen; jeder andere Wert ist ungültig.

usage.count zählt unterschiedliche aktive Inhaltszeilen oder Locales, deren indexierte Quelle das Medium referenziert, plus jede Site-Einstellung, die es auswählt (logo, favicon, seo.defaultOgImage). Wiederholte Referenzen in einem Eintrag zählen einmal; Papierkorb-Einträge nicht. Die Zahl ist nur für Aufrufer sichtbar, die Entwürfe lesen dürfen; andere autorisierte Medien-Leser erhalten count: null, weil die Zahl Entwurfsinhalte verraten könnte.

GET /media/{id}/usage liefert referenzierende Inhaltseinträge seitenweise. Jede Seite enthält auch siteSettings, die Site-Einstellungen, die das Medium auswählen, z. B. [{ "setting": "favicon" }]. Site-Einstellungen werden pro Anfrage aus den gespeicherten Einstellungen gelesen und hängen nicht vom Nutzungsindex ab.

Jedes Nutzungsergebnis enthält einen Abdeckungsstatus:

StatusBedeutung
completeJede registrierte Collection hat aktuelle Nutzungsabdeckung.
neverKeine registrierte Collection hat eine anfängliche Nutzungsreparatur abgeschlossen.
runningEine Reparatur läuft.
partialNur ein Teil der registrierten Collections hat aktuelle Abdeckung.
failedAbdeckung ist für den registrierten Collection-Satz fehlgeschlagen.
staleDer Index ist älter als der beschriebene Inhalt.
unknownDer gespeicherte Zustand wird von dieser EmDash-Version nicht erkannt.

Nur bei complete kann eine Null-Anzahl innerhalb der indexierten Feldtypen als vollständig gelten. Zähler sind bei gleichzeitigen Schreibvorgängen beratend; sie sperren das Medium nicht und garantieren keine sichere Löschung. Die Nutzungsindexierung umfasst Bild- und Dateifelder, Repeater-Bildfelder, Portable-Text-Bild- und Galerie-Blöcke sowie in EmDash-Collections deklarierte Medien behaltener Blockversionen. Logo, Favicon und Standard-Social-Bild der Site werden ebenfalls gemeldet. Nutzung umfasst keine benutzerdefinierten Portable-Text-Blöcke, Anwendungscode, gerendertes HTML, andere Einstellungen, Menüs, Widgets, Plugin-Daten, externe Sites oder reine Provider-Assets.

Direkter Multipart-Upload

Senden Sie eine Datei durch EmDash, indem Sie sie als file-Feld einer Multipart-Anfrage posten:

curl --request POST \
	--header "Authorization: Bearer $EMDASH_TOKEN" \
	--form "file=@./cover.jpg;type=image/jpeg" \
	https://example.com/_emdash/api/media

curl fügt die Multipart-Grenze hinzu. Setzen Sie den Header Content-Type nicht manuell. Das OpenAPI-Schema MediaDirectUploadBody listet optionale Metadatenfelder; Antwortschemas unterscheiden neuen Upload von dedupliziertem bestehendem Element.

Der Multipart-Body kann auch Bild-width, height, eine fieldId, deren MIME-Typ-Allowlist gelten soll, und ein verkleinertes thumbnail für einen Low-Quality-Platzhalter enthalten. Eine neue Datei liefert 201 Created und ist sofort bereit. Identische Bytes liefern das bestehende Medium mit 200 OK und deduplicated: true.

Upload-Ziel-Ablauf

Verwenden Sie den Upload-Ziel-Ablauf, wenn der Client direkt in S3-kompatiblen Speicher hochladen kann. Das Medium bleibt pending und erscheint erst in der Standardbibliothek, wenn die Bestätigung gelingt.

  1. Upload-Ziel anfordern

    POST /_emdash/api/media/upload-url
    Authorization: Bearer $EMDASH_TOKEN
    Content-Type: application/json
    
    {
    	"filename": "cover.jpg",
    	"contentType": "image/jpeg",
    	"size": 102400
    }

    Die Antwort liefert uploadUrl, method, headers, mediaId, storageKey und ein Ablaufdatum. Stimmt contentHash mit einer bestehenden Datei gleichen MIME-Typs und gleicher Größe überein, setzt die Antwort stattdessen existing: true; verwenden Sie dieses Medium und laden Sie keine weitere Kopie hoch oder bestätigen Sie sie.

  2. Bytes hochladen

    Verwenden Sie zurückgegebene Methode und Header. Lösen Sie eine root-relative URL gegen die EmDash-Site auf und fügen Sie das Bearer-Token hinzu. Senden Sie nur die zurückgegebenen Upload-Header an eine absolute URL auf anderer Origin.

  3. Upload bestätigen

    POST /_emdash/api/media/01JMEDIA000000000000000000/confirm
    Authorization: Bearer $EMDASH_TOKEN
    Content-Type: application/json
    
    {
    	"size": 102400,
    	"width": 1920,
    	"height": 1080
    }

    Die Bestätigung prüft das gespeicherte Objekt und ändert den Status von pending zu ready. Angegebene Größe und Abmessungen müssen zur hochgeladenen Datei passen.

Lokaler Speicher und natives R2 liefern ein same-origin EmDash-Upload-Ziel. S3-kompatibler Speicher kann eine signierte externe URL liefern. Pending-Elemente fehlen in der Standard-Medienliste, bis die Bestätigung gelingt.

Upload-Fehler

Die folgenden Fehler erfordern unterschiedliche Wiederherstellungsmaßnahmen:

StatusCodeAktion
400NO_FILEFügen Sie das Feld file zur Multipart-Anfrage hinzu oder senden Sie den fehlenden Upload-Body.
400INVALID_TYPEVerwenden Sie einen erlaubten MIME-Typ, der zum pending-Medium passt.
400VALIDATION_ERRORKorrigieren Sie fehlende oder ungültige Metadaten, einschließlich Werte über dem konfigurierten Größenlimit.
400FILE_NOT_FOUNDLaden Sie das Objekt zum zurückgegebenen Ziel hoch, bevor Sie bestätigen.
400UPLOAD_SIZE_MISMATCHStarten Sie den Ablauf mit der korrekten Größe neu; deklarierte, hochgeladene und bestätigte Größen müssen übereinstimmen.
400 or 409INVALID_STATELesen Sie das Medium vor einem erneuten Versuch. Es ist möglicherweise nicht mehr pending, oder eine andere Anfrage hat es während der Bestätigung geändert.
404NOT_FOUNDVerwenden Sie eine bestehende pending-Medien-ID.
413PAYLOAD_TOO_LARGEVerkleinern Sie die Datei oder erhöhen Sie maxUploadSize, bevor Sie erneut hochladen.

Medienordner

Ordnernamen werden getrimmt, auf 200 Zeichen begrenzt und nach Unicode-Normalisierung und Kleinschreibung verglichen. Namen wie Photos, photos und PHOTOS kollidieren daher. Das Löschen eines Ordners verschiebt Medien zurück in die Hauptbibliothek; es löscht keine Medien, ändert keine Medien-IDs oder URLs und ändert keine Nutzungsdatensätze.

Medien-Nutzung reparieren

Aktivierung, Fortschritt, Workqueues, Löschbereinigung und Reparatur der Medien-Nutzung sind Operator-Operationen unter /_emdash/api/admin/media-usage/. Session-Benutzer benötigen schema:manage; Bearer-Tokens zusätzlich den Scope admin.

Ist Tracking aus, pausieren Sie direkte Datenbank-Schreiber vor der Aktivierung. EmDash blockiert vorübergehend Inhalts- und Schema-Schreibvorgänge über seine APIs während des Setups, kann aber keinen anderen Prozess stoppen, der direkt in die Datenbank schreibt.

  1. Direkte Datenbank-Schreiber stoppen und laufende Schreibvorgänge abwarten.
  2. Aktivierungszustand lesen. expanded bedeutet Tracking aus, activating bedeutet EmDash bereitet Collections vor, active bedeutet neue Medien-Referenz-Änderungen werden verfolgt.
  3. Eine Aktivierungsanfrage mit { "writersDrained": true } senden.
  4. Fortschrittsanfragen nacheinander senden und jeweils auf nextRequestInMs warten, bis die Aktivierung active ist.
  5. Direkte Datenbank-Schreiber wieder aufnehmen.
  6. Fortschrittsanfragen fortsetzen, bis historische Indexierung ready ist und nextRequestInMs null ist.

Bei Timeout oder 409/500 einer Schreibanfrage Aktivierungs- und Fortschrittszustand lesen, bevor Sie erneut versuchen. Abgeschlossene Batches bleiben protokolliert. Ist lastErrorCode gesetzt, Schreiber gestoppt lassen, Problem beheben und einen bestätigten Retry senden. Aktivierung kann nach Start nicht abgebrochen oder zurückgesetzt werden — testen Sie daher auf einer Staging-Kopie und halten Sie ein aktuelles Datenbank-Backup bereit.

Work-List-Operationen zeigen fehlgeschlagene oder verzögerte Eintrags-Indexierung, ohne Inhalt, Medienreferenzen, Lease-Tokens, rohe DB-Fehler oder exakte Backlog-Zahl zurückzugeben. Retry eines Elements ist idempotent. 409 WORK_LEASE_ACTIVE bedeutet, ein Worker verarbeitet das Element noch; die Antwort enthält details.leaseExpiresAt — warten Sie bis dahin und lesen Sie erneut. 409 WORK_CHANGED bedeutet, eine andere Anfrage hat das Work-Item geändert; lesen Sie den aktuellen Zustand statt neueres Work zu überschreiben.

Die Reparatur-Operation akzeptiert { "scope": "collection", "collection": "articles" } oder { "scope": "all" }. Reparatur aller Collections läuft synchron und sequenziell und kann auf großen Sites lange dauern. Eine 200-Antwort kann trotzdem partial, failed oder stale melden — prüfen Sie data.status, Collection-Status und Quellzähler, bevor Sie die Reparatur als abgeschlossen betrachten.

Site-Transfer

Transfer-Operationen unter /_emdash/api/admin/transfer/ exportieren eine Site als Site-Paket und importieren eines in eine leere Site. Der Site-Transfer-Leitfaden beschreibt Export, Upload, Analyse, Ausführung und Receipt-Workflow.

Session-Benutzer benötigen transfer:export oder transfer:import, die nur Administratoren haben. Bearer-Tokens benötigen admin oder den von jeder Operation genannten Scope transfer:export, transfer:analyze oder transfer:execute. Genehmigungsoperationen akzeptieren nur angemeldete Sessions. Sie entscheiden Anfragen der MCP-Tools site_export_start und site_import_start; REST-Export und -Execute nehmen keine Genehmigung entgegen.

Während ein Import läuft und nach Fehlschlag oder Abbruch bis zum Abandon blockieren die meisten anderen Schreiboperationen mit 503 TRANSFER_IMPORT_IN_PROGRESS. Der Leitfaden listet die Operationen, die weiterhin verfügbar bleiben.

Paginierung

Listenoperationen beschreiben Paginierungsparameter in OpenAPI. Die meisten Cursor-paginierten Operationen akzeptieren einen undurchsichtigen cursor und limit von 1 bis 100, Standard 50. Geben Sie nextCursor der vorherigen Antwort unverändert zurück; analysieren oder konstruieren Sie ihn nicht. Einige Medienoperationen unterstützen nummerierte Seiten; spezialisierte Listen andere Limits — generierte Clients sollten dem Schema jeder Operation folgen.

Such-Tokenizer

Die Search-Enable-Operation speichert pro Collection einen Tokenizer. Änderung bei aktivierter Suche baut den Index der Collection neu.

WertVerwendung
porter unicode61Standard für englische Inhalte mit Porter-Stemming.
unicode61Sprachen mit Worttrennern ohne englisches Stemming.
trigramText ohne Leerzeichen, u. a. Japanisch, Chinesisch, Thai, Khmer, Lao und Birmanisch, oder Collections mit Substring-Matching. Anfragen kürzer als drei Unicode-Zeichen liefern keine Treffer.

Deaktivieren der Suche behält den gespeicherten Tokenizer für das nächste Enable. Rebuild nutzt gespeicherten Tokenizer und Feldgewichte der Collection.

Kommentare und Weiterleitungen

Öffentliche Kommentare landen in der Moderations-Warteschlange. Admin-Kommentaroperationen listen alle Status, liefern Zähler, aktualisieren einen Status, moderieren bulk und löschen dauerhaft. 429 bedeutet Rate-Limit für Einreichungen.

Weiterleitungsoperationen verwalten Regeln und 404-Log getrennt. Prune entfernt per Body ausgewählte Einträge; DELETE /redirects/404s leert das gesamte Log. Keine der Operationen löscht Weiterleitungsregeln.