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
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/content/{collection} | listContent | List content items |
POST | /_emdash/api/content/{collection} | createContent | Create a content item |
GET | /_emdash/api/content/{collection}/{id} | getContent | Get a content item |
PUT | /_emdash/api/content/{collection}/{id} | updateContent | Update a content item |
DELETE | /_emdash/api/content/{collection}/{id} | deleteContent | Delete a content item (soft delete) |
POST | /_emdash/api/content/{collection}/{id}/publish | publishContent | Publish a content item |
POST | /_emdash/api/content/{collection}/{id}/unpublish | unpublishContent | Unpublish a content item |
POST | /_emdash/api/content/{collection}/{id}/schedule | scheduleContent | Schedule content for future publishing |
DELETE | /_emdash/api/content/{collection}/{id}/schedule | unscheduleContent | Cancel scheduled publishing |
POST | /_emdash/api/content/{collection}/{id}/duplicate | duplicateContent | Duplicate a content item |
POST | /_emdash/api/content/{collection}/{id}/restore | restoreContent | Restore a content item from trash |
DELETE | /_emdash/api/content/{collection}/{id}/permanent | permanentDeleteContent | Permanently delete a content item |
GET | /_emdash/api/content/{collection}/{id}/compare | compareContent | Compare live and draft revisions |
POST | /_emdash/api/content/{collection}/{id}/discard-draft | discardDraft | Discard draft changes |
GET | /_emdash/api/content/{collection}/{id}/lock | getEntryLock | Read the entry’s edit lock |
POST | /_emdash/api/content/{collection}/{id}/lock | acquireEntryLock | Take or refresh the entry’s edit lock |
DELETE | /_emdash/api/content/{collection}/{id}/lock | releaseEntryLock | Release the caller’s edit lock |
GET | /_emdash/api/content/{collection}/{id}/translations | getContentTranslations | Get translations for a content item |
GET | /_emdash/api/content/{collection}/{id}/terms/{taxonomy} | getContentTerms | Get taxonomy terms assigned to a content item |
POST | /_emdash/api/content/{collection}/{id}/terms/{taxonomy} | setContentTerms | Set taxonomy terms on a content item |
GET | /_emdash/api/content/{collection}/authors | listContentAuthors | List distinct authors of a collection’s content |
GET | /_emdash/api/content/{collection}/trash | listTrashedContent | List trashed content items |
Medien
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/media | listMedia | List media items |
POST | /_emdash/api/media | uploadMedia | Upload a media item |
GET | /_emdash/api/media/folders | listMediaFolders | List media folders |
POST | /_emdash/api/media/folders | createMediaFolder | Create a media folder |
GET | /_emdash/api/media/folders/{id} | getMediaFolder | Get a media folder |
PUT | /_emdash/api/media/folders/{id} | updateMediaFolder | Update a media folder |
DELETE | /_emdash/api/media/folders/{id} | deleteMediaFolder | Delete a media folder |
GET | /_emdash/api/media/{id} | getMedia | Get a media item |
PUT | /_emdash/api/media/{id} | updateMedia | Update media metadata |
DELETE | /_emdash/api/media/{id} | deleteMedia | Delete a media item |
GET | /_emdash/api/media/{id}/usage | getMediaUsage | Get media usage details |
PUT | /_emdash/api/media/{id}/replace | replaceMediaImage | Replace a media image |
POST | /_emdash/api/admin/media-usage/repair | repairMediaUsage | Repair media usage indexes |
GET | /_emdash/api/admin/media-usage/progress | getMediaUsageProgress | Get media usage indexing progress |
POST | /_emdash/api/admin/media-usage/progress | advanceMediaUsageProgress | Advance media usage indexing |
GET | /_emdash/api/admin/media-usage/work | listMediaUsageWork | List durable media usage work |
GET | /_emdash/api/admin/media-usage/activation | getMediaUsageActivation | Get media usage activation status |
POST | /_emdash/api/admin/media-usage/activation | advanceMediaUsageActivation | Advance media usage activation |
POST | /_emdash/api/admin/media-usage/work/retry | retryMediaUsageWork | Retry one durable media usage job |
GET | /_emdash/api/admin/media-usage/collection-deletions | listMediaUsageCollectionDeletions | List durable collection deletions |
POST | /_emdash/api/admin/media-usage/collection-deletions/retry | retryMediaUsageCollectionDeletion | Retry one collection deletion |
POST | /_emdash/api/media/upload-url | getMediaUploadUrl | Get a media upload target |
POST | /_emdash/api/media/{id}/confirm | confirmMediaUpload | Confirm a media upload |
PUT | /_emdash/api/media/{id}/upload | uploadPendingMedia | Upload a pending media file through EmDash |
Schema
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/schema/block-types | listBlockTypes | List block types |
POST | /_emdash/api/schema/block-types | createBlockType | Create a block type |
GET | /_emdash/api/schema/block-types/{slug} | getBlockType | Get a block type |
PUT | /_emdash/api/schema/block-types/{slug} | updateBlockType | Update a block type |
POST | /_emdash/api/schema/block-types/{slug}/versions/{version}/activate | activateBlockTypeVersion | Activate a block type version |
GET | /_emdash/api/schema/collections | listCollections | List all collections |
POST | /_emdash/api/schema/collections | createCollection | Create a collection |
GET | /_emdash/api/schema/collections/{slug} | getCollection | Get a collection |
PUT | /_emdash/api/schema/collections/{slug} | updateCollection | Update a collection |
DELETE | /_emdash/api/schema/collections/{slug} | deleteCollection | Delete a collection |
GET | /_emdash/api/schema/collections/{slug}/fields | listFields | List fields for a collection |
POST | /_emdash/api/schema/collections/{slug}/fields | createField | Create a field |
GET | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | getField | Get a field |
PUT | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | updateField | Update a field |
DELETE | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | deleteField | Delete a field |
POST | /_emdash/api/schema/collections/reorder | reorderCollections | Reorder collections in the admin sidebar |
POST | /_emdash/api/schema/collections/{slug}/fields/reorder | reorderFields | Reorder fields in a collection |
GET | /_emdash/api/schema/orphans | listOrphanedTables | List orphaned content tables |
POST | /_emdash/api/schema/orphans/{slug} | registerOrphanedTable | Register an orphaned table as a collection |
Kommentare
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/comments/{collection}/{contentId} | listPublicComments | List approved comments for content |
POST | /_emdash/api/comments/{collection}/{contentId} | createComment | Submit a new comment |
GET | /_emdash/api/admin/comments | listAdminComments | List comments for moderation |
GET | /_emdash/api/admin/comments/counts | getCommentCounts | Get comment status counts |
POST | /_emdash/api/admin/comments/bulk | bulkCommentAction | Bulk approve, spam, trash, or delete comments |
GET | /_emdash/api/admin/comments/{id} | getComment | Get a single comment |
DELETE | /_emdash/api/admin/comments/{id} | deleteComment | Permanently delete a comment |
PUT | /_emdash/api/admin/comments/{id}/status | updateCommentStatus | Change comment status |
Taxonomien
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/taxonomies | listTaxonomies | List all taxonomy definitions |
GET | /_emdash/api/taxonomies/{name} | getTaxonomy | Get a taxonomy definition |
PUT | /_emdash/api/taxonomies/{name} | updateTaxonomy | Update a taxonomy definition |
DELETE | /_emdash/api/taxonomies/{name} | deleteTaxonomy | Delete a taxonomy, its terms, and their content assignments |
GET | /_emdash/api/taxonomies/{name}/translations | listTaxonomyTranslations | List every locale variant of a taxonomy definition |
POST | /_emdash/api/taxonomies/{name}/reorder | reorderTerms | Set the manual order of one sibling group of terms |
GET | /_emdash/api/taxonomies/{name}/terms | listTerms | List terms for a taxonomy |
POST | /_emdash/api/taxonomies/{name}/terms | createTerm | Create a term |
GET | /_emdash/api/taxonomies/{name}/terms/{slug} | getTerm | Get a term by slug |
PUT | /_emdash/api/taxonomies/{name}/terms/{slug} | updateTerm | Update a term |
DELETE | /_emdash/api/taxonomies/{name}/terms/{slug} | deleteTerm | Delete a term |
Menüs
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/menus | listMenus | List all menus with item counts |
POST | /_emdash/api/menus | createMenu | Create a menu |
GET | /_emdash/api/menus/{name} | getMenu | Get a menu with all items |
PUT | /_emdash/api/menus/{name} | updateMenu | Update a menu |
DELETE | /_emdash/api/menus/{name} | deleteMenu | Delete a menu and its items |
POST | /_emdash/api/menus/{name}/items | createMenuItem | Add an item to a menu |
PUT | /_emdash/api/menus/{name}/items/{id} | updateMenuItem | Update a menu item |
DELETE | /_emdash/api/menus/{name}/items/{id} | deleteMenuItem | Delete a menu item |
POST | /_emdash/api/menus/{name}/reorder | reorderMenuItems | Batch reorder menu items |
Bereiche
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/sections | listSections | List sections |
POST | /_emdash/api/sections | createSection | Create a section |
GET | /_emdash/api/sections/{slug} | getSection | Get a section by slug |
PUT | /_emdash/api/sections/{slug} | updateSection | Update a section |
DELETE | /_emdash/api/sections/{slug} | deleteSection | Delete a section |
Widgets
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/widget-areas | listWidgetAreas | List all widget areas |
POST | /_emdash/api/widget-areas | createWidgetArea | Create a widget area |
GET | /_emdash/api/widget-areas/{name} | getWidgetArea | Get a widget area with widgets |
DELETE | /_emdash/api/widget-areas/{name} | deleteWidgetArea | Delete a widget area and its widgets |
POST | /_emdash/api/widget-areas/{name}/widgets | createWidget | Add a widget to an area |
PUT | /_emdash/api/widget-areas/{name}/widgets/{id} | updateWidget | Update a widget |
DELETE | /_emdash/api/widget-areas/{name}/widgets/{id} | deleteWidget | Delete a widget |
POST | /_emdash/api/widget-areas/{name}/reorder | reorderWidgets | Reorder widgets in an area |
Einstellungen
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/settings | getSettings | Get site settings |
PUT | /_emdash/api/settings | updateSettings | Update site settings |
Suche
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/search | search | Full-text search across collections |
GET | /_emdash/api/search/suggest | searchSuggest | Autocomplete search suggestions |
POST | /_emdash/api/search/rebuild | rebuildSearchIndex | Rebuild the search index for a collection |
POST | /_emdash/api/search/enable | enableSearch | Enable or disable search for a collection |
GET | /_emdash/api/search/stats | getSearchStats | Get search index statistics |
Weiterleitungen
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/redirects | listRedirects | List redirects |
POST | /_emdash/api/redirects | createRedirect | Create a redirect rule |
GET | /_emdash/api/redirects/{id} | getRedirect | Get a redirect |
PUT | /_emdash/api/redirects/{id} | updateRedirect | Update a redirect |
DELETE | /_emdash/api/redirects/{id} | deleteRedirect | Delete a redirect |
GET | /_emdash/api/redirects/404s | listNotFoundEntries | List 404 log entries |
POST | /_emdash/api/redirects/404s | pruneNotFoundLog | Prune old 404 log entries |
DELETE | /_emdash/api/redirects/404s | clearNotFoundLog | Clear all 404 log entries |
GET | /_emdash/api/redirects/404s/summary | getNotFoundSummary | Get 404 summary grouped by path |
Benutzer
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/admin/users | listUsers | List users |
GET | /_emdash/api/admin/users/{id} | getUser | Get user details |
PUT | /_emdash/api/admin/users/{id} | updateUser | Update a user |
POST | /_emdash/api/admin/users/{id}/disable | disableUser | Disable a user account |
POST | /_emdash/api/admin/users/{id}/enable | enableUser | Enable a user account |
GET | /_emdash/api/admin/allowed-domains | listAllowedDomains | List allowed email domains |
POST | /_emdash/api/admin/allowed-domains | createAllowedDomain | Add an allowed email domain |
PUT | /_emdash/api/admin/allowed-domains/{domain} | updateAllowedDomain | Update an allowed domain |
DELETE | /_emdash/api/admin/allowed-domains/{domain} | deleteAllowedDomain | Remove an allowed domain |
Transfer
| Methode | Pfad | Operation | Kurzbeschreibung |
|---|---|---|---|
GET | /_emdash/api/admin/transfer/capabilities | getTransferCapabilities | Get site transfer capabilities |
GET | /_emdash/api/admin/transfer/imports | listTransferImports | List site imports |
POST | /_emdash/api/admin/transfer/imports | createTransferImport | Create a site import |
GET | /_emdash/api/admin/transfer/imports/{id} | getTransferImport | Get a site import |
GET | /_emdash/api/admin/transfer/imports/{id}/missing | listTransferImportMissingFiles | List package files still to upload |
PUT | /_emdash/api/admin/transfer/imports/{id}/files/{path} | uploadTransferImportFile | Upload one package file |
POST | /_emdash/api/admin/transfer/imports/{id}/analyze | analyzeTransferImport | Advance import analysis |
GET | /_emdash/api/admin/transfer/imports/{id}/plan | getTransferImportPlan | Get an import plan |
POST | /_emdash/api/admin/transfer/imports/{id}/cancel | cancelTransferImport | Cancel a site import |
POST | /_emdash/api/admin/transfer/imports/{id}/abandon | abandonTransferImport | Abandon a failed or cancelled import |
POST | /_emdash/api/admin/transfer/imports/{id}/execute | executeTransferImport | Start a planned import |
POST | /_emdash/api/admin/transfer/imports/{id}/advance | advanceTransferImport | Advance an executing import |
GET | /_emdash/api/admin/transfer/imports/{id}/receipt | getTransferImportReceipt | Get an import receipt |
GET | /_emdash/api/admin/transfer/exports | listTransferExports | List site exports |
POST | /_emdash/api/admin/transfer/exports | createTransferExport | Start a site export |
GET | /_emdash/api/admin/transfer/exports/{id} | getTransferExport | Get a site export |
POST | /_emdash/api/admin/transfer/exports/{id}/advance | advanceTransferExport | Advance a site export |
GET | /_emdash/api/admin/transfer/exports/{id}/manifest | getTransferExportManifest | Download an export manifest |
GET | /_emdash/api/admin/transfer/exports/{id}/files/{path} | downloadTransferExportFile | Download one export file |
GET | /_emdash/api/admin/transfer/exports/{id}/archive | downloadTransferExportArchive | Download an export archive |
GET | /_emdash/api/admin/transfer/approvals | listTransferApprovals | List transfer approvals |
POST | /_emdash/api/admin/transfer/approvals/{id}/approve | approveTransferApproval | Approve a transfer request |
POST | /_emdash/api/admin/transfer/approvals/{id}/deny | denyTransferApproval | Deny 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:
| Status | Bedeutung |
|---|---|
complete | Jede registrierte Collection hat aktuelle Nutzungsabdeckung. |
never | Keine registrierte Collection hat eine anfängliche Nutzungsreparatur abgeschlossen. |
running | Eine Reparatur läuft. |
partial | Nur ein Teil der registrierten Collections hat aktuelle Abdeckung. |
failed | Abdeckung ist für den registrierten Collection-Satz fehlgeschlagen. |
stale | Der Index ist älter als der beschriebene Inhalt. |
unknown | Der 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.
-
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,storageKeyund ein Ablaufdatum. StimmtcontentHashmit einer bestehenden Datei gleichen MIME-Typs und gleicher Größe überein, setzt die Antwort stattdessenexisting: true; verwenden Sie dieses Medium und laden Sie keine weitere Kopie hoch oder bestätigen Sie sie. -
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.
-
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
pendingzuready. 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:
| Status | Code | Aktion |
|---|---|---|
400 | NO_FILE | Fügen Sie das Feld file zur Multipart-Anfrage hinzu oder senden Sie den fehlenden Upload-Body. |
400 | INVALID_TYPE | Verwenden Sie einen erlaubten MIME-Typ, der zum pending-Medium passt. |
400 | VALIDATION_ERROR | Korrigieren Sie fehlende oder ungültige Metadaten, einschließlich Werte über dem konfigurierten Größenlimit. |
400 | FILE_NOT_FOUND | Laden Sie das Objekt zum zurückgegebenen Ziel hoch, bevor Sie bestätigen. |
400 | UPLOAD_SIZE_MISMATCH | Starten Sie den Ablauf mit der korrekten Größe neu; deklarierte, hochgeladene und bestätigte Größen müssen übereinstimmen. |
400 or 409 | INVALID_STATE | Lesen 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. |
404 | NOT_FOUND | Verwenden Sie eine bestehende pending-Medien-ID. |
413 | PAYLOAD_TOO_LARGE | Verkleinern 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.
- Direkte Datenbank-Schreiber stoppen und laufende Schreibvorgänge abwarten.
- Aktivierungszustand lesen.
expandedbedeutet Tracking aus,activatingbedeutet EmDash bereitet Collections vor,activebedeutet neue Medien-Referenz-Änderungen werden verfolgt. - Eine Aktivierungsanfrage mit
{ "writersDrained": true }senden. - Fortschrittsanfragen nacheinander senden und jeweils auf
nextRequestInMswarten, bis die Aktivierungactiveist. - Direkte Datenbank-Schreiber wieder aufnehmen.
- Fortschrittsanfragen fortsetzen, bis historische Indexierung
readyist undnextRequestInMsnullist.
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.
| Wert | Verwendung |
|---|---|
porter unicode61 | Standard für englische Inhalte mit Porter-Stemming. |
unicode61 | Sprachen mit Worttrennern ohne englisches Stemming. |
trigram | Text 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.