REST-API-Referenz

Auf dieser Seite

EmDash stellt eine REST-API unter /_emdash/api/ für Inhaltsverwaltung, Medien-Uploads und Schema-Operationen bereit.

Authentifizierung

API-Anfragen erfordern Authentifizierung über ein Bearer-Token im Authorization-Header:

Authorization: Bearer <token>

Generieren Sie Token über die Admin-Oberfläche oder programmgesteuert.

Antwortformat

Alle Antworten folgen einem einheitlichen Format. Eine erfolgreiche Antwort umhüllt das Ergebnis in data:

{
  "success": true,
  "data": { ... }
}

Eine Fehlerantwort enthält einen Code, eine Nachricht und optionale Details:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message",
    "details": { ... }
  }
}

Inhalts-Endpunkte

Inhalte auflisten

GET /_emdash/api/content/:collection

Parameter

ParameterTypBeschreibung
collectionstringCollection-Slug (Pfad)
cursorstringPaginierungs-Cursor (Query)
limitnumberEinträge pro Seite (Query, Standard: 50)
statusstringNach Status filtern (Query)
orderBystringSortierfeld (Query)
orderstringSortierrichtung: asc oder desc (Query)

Antwort

{
  "success": true,
  "data": {
    "items": [
      {
        "id": "01HXK5MZSN...",
        "type": "posts",
        "slug": "hello-world",
        "data": { "title": "Hello World", ... },
        "status": "published",
        "createdAt": "2025-01-24T12:00:00Z",
        "updatedAt": "2025-01-24T12:00:00Z"
      }
    ],
    "nextCursor": "eyJpZCI6..."
  }
}

Inhalt abrufen

GET /_emdash/api/content/:collection/:id

Antwort

{
  "success": true,
  "data": {
    "item": {
      "id": "01HXK5MZSN...",
      "type": "posts",
      "slug": "hello-world",
      "data": { "title": "Hello World", ... },
      "status": "published",
      "createdAt": "2025-01-24T12:00:00Z",
      "updatedAt": "2025-01-24T12:00:00Z"
    }
  }
}

Inhalt erstellen

POST /_emdash/api/content/:collection
Content-Type: application/json

Anfragekörper

{
  "data": {
    "title": "New Post",
    "content": [...]
  },
  "slug": "new-post",
  "status": "draft"
}

Antwort

{
  "success": true,
  "data": {
    "item": { ... }
  }
}

Inhalt aktualisieren

PUT /_emdash/api/content/:collection/:id
Content-Type: application/json

Anfragekörper

{
	"data": {
		"title": "Updated Title"
	},
	"status": "published"
}

Inhalt löschen

DELETE /_emdash/api/content/:collection/:id

Antwort

{
	"success": true,
	"data": {
		"success": true
	}
}

Medien-Endpunkte

Medien auflisten

GET /_emdash/api/media?includeUsage=1

Parameter

ParameterTypBeschreibung
cursorstringUndurchsichtiger Paginierungs-Cursor
limitnumberEinträge pro Seite, von 1 bis 100 (Standard: 50)
mimeTypestringNach einem oder mehreren kommaseparierten MIME-Typen filtern
qstringGroß-/Kleinschreibung-unabhängige Dateinamensuche
includeUsage1Abdeckungsbezogene usage-Zusammenfassung für jeden zurückgegebenen Eintrag einschließen

Antwort

{
	"data": {
		"items": [
			{
				"id": "01HXK5MZSN...",
				"filename": "photo.jpg",
				"mimeType": "image/jpeg",
				"size": 102400,
				"width": 1920,
				"height": 1080,
				"url": "/_emdash/api/media/file/uploads/photo.jpg",
				"createdAt": "2025-01-24T12:00:00Z",
				"usage": {
					"count": 3,
					"coverage": {
						"scope": "all_content_collections",
						"status": "complete"
					}
				}
			}
		],
		"nextCursor": "eyJpZCI6..."
	}
}

Medien abrufen

GET /_emdash/api/media/:id?includeUsage=1

includeUsage ist sowohl bei List als auch bei Get optional. Der einzige akzeptierte Wert ist 1. Wenn weggelassen, wird die usage-Eigenschaft weggelassen und der Server führt keine Nutzungsabfragen durch.

Nutzungszusammenfassungen

usage.count ist die Anzahl der eindeutigen aktiven EmDash-Inhaltszeilen oder Locales, deren ausgewählte aktuelle indizierte Quelle das Medienelement referenziert. Wiederholte Referenzen und mehrere Quellvarianten für denselben Inhaltseintrag zählen einmal. Papierkorb-Inhalte werden nicht gezählt.

Eine numerische Anzahl kann Entwurfs-ähnliche Inhalte offenlegen. Sie wird nur zurückgegeben, wenn ein Sitzungsbenutzer content:read_drafts hat, oder wenn ein API-Token den admin-Scope hat und sein zugehöriger Benutzer ebenfalls diese Berechtigung besitzt. Andere Medienleser erhalten usage.count: null; dies ist eine erfolgreiche geschwärzte Antwort, kein Fehler.

Jede angeforderte Zusammenfassung enthält eine aggregierte Abdeckung für alle aktuell registrierten Inhalts-Collections:

StatusBedeutung
completeJede registrierte Collection hat aktuelle, vollständige Nutzungsabdeckung
neverKeine registrierte Collection hat eine erste Nutzungsreparatur abgeschlossen
runningEine Nutzungsreparatur läuft gerade
partialDie Abdeckung ist gemischt oder nur ein Teil des registrierten Umfangs wurde indiziert
failedDie Abdeckung ist im registrierten Umfang fehlgeschlagen
staleDie indizierte Abdeckung ist veraltet
unknownDie gespeicherte Abdeckung enthält einen Zustand, den diese Version nicht erkennt

Nur complete unterstützt eine umfangsbezogene vollständige Null-Aussage innerhalb der von EmDash verwalteten Felder, die unten beschrieben werden. Zählungen mit einem anderen Status sind indizierte Projektionen und können über- oder unterberichten. Selbst vollständige Ergebnisse sind bei gleichzeitigen Schreibvorgängen beratend; Nutzungslesungen sind kein transaktionaler Lock und dürfen nicht als Löschgarantie verwendet werden.

Medien-Nutzungsdetails abrufen

GET /_emdash/api/media/:id/usage?limit=50&cursor=...

Dieser Endpunkt erfordert media:read und content:read_drafts. Token-authentifizierte Aufrufer benötigen auch den admin-Scope; der Token-Scope umgeht nicht die Berechtigungen des zugehörigen Benutzers.

limit steuert Inhaltseintrag-Gruppen pro Seite, von 1 bis 100 (Standard: 50). Die Paginierung teilt niemals die Quellen oder Vorkommen für eine zurückgegebene Eintragsgruppe auf.

{
	"data": {
		"items": [
			{
				"collection": "posts",
				"contentId": "01CONTENT...",
				"title": "Launch notes",
				"slug": "launch-notes",
				"locale": "en",
				"status": "published",
				"scheduledAt": null,
				"deletedAt": null,
				"sources": [
					{
						"variant": "columns",
						"occurrences": [
							{
								"fieldSlug": "hero",
								"fieldPath": "hero",
								"occurrenceIndex": 0,
								"referenceType": "image_field"
							}
						]
					}
				]
			}
		],
		"nextCursor": "eyJvcmRlclZhbHVlIjoicG9zdHMiLCJpZCI6IjAxLi4uIn0",
		"coverage": {
			"scope": "all_content_collections",
			"status": "complete"
		}
	}
}

Autorisierte Details umfassen aktive und gelöschte Einträge. Ein nicht-null deletedAt identifiziert einen gelöschten Eintrag. Quellen sind columns oder draft_overlay; Vorkommen identifizieren das unterstützte Feld und den Pfad, ohne interne Index-Metadaten offenzulegen.

Die Mediennutzung umfasst lokale Medienreferenzen in Top-Level-Bild- und Dateifeldern, Repeater-Bildfeldern und Portable-Text-Bildblöcken, die von EmDash-Inhalts-Collections verwaltet werden. Sie scannt keinen benutzerdefinierten Code, gerendertes HTML, Einstellungen, Menüs, Widgets, Plugin-private Daten, externe Seiten oder ausschließlich anbieterspezifische Assets.

Medien erstellen

POST /_emdash/api/media
Content-Type: application/json

Anfragekörper

{
	"filename": "photo.jpg",
	"mimeType": "image/jpeg",
	"size": 102400,
	"width": 1920,
	"height": 1080,
	"storageKey": "uploads/photo.jpg"
}

Medien aktualisieren

PUT /_emdash/api/media/:id
Content-Type: application/json

Anfragekörper

{
	"alt": "Photo description",
	"caption": "Photo caption"
}

Medien löschen

DELETE /_emdash/api/media/:id

Mediennutzung reparieren

POST /_emdash/api/admin/media-usage/repair
Content-Type: application/json
X-EmDash-Request: 1

Repariert den Inhalts-Mediennutzungs-Index für eine Collection oder für alle Inhalts-Collections. Dies ist ein Admin-/Operator-Endpunkt: Sitzungs-authentifizierte Aufrufer benötigen schema:manage, und Bearer-Token müssen den admin-Scope haben, da die Route unter /_emdash/api/admin liegt.

Die Reparatur aller Inhalte läuft synchron und sequenziell in der aktuellen Version. Sie kann bei großen Websites teuer sein, daher sollten Aufrufer sie bewusst auslösen und auf die Antwort warten.

Anfragekörper

Eine Collection reparieren:

{
	"scope": "collection",
	"collection": "posts"
}

Alle Inhalts-Collections reparieren:

{
	"scope": "all"
}

Der Anfragekörper ist erforderlich. Ungültige Slugs, unbekannte Anfrageschlüssel, fehlender scope und Anfragen ohne Body geben 400 zurück, anstatt standardmäßig alle Inhalte zu reparieren.

Antwort

Der Endpunkt gibt 200 zurück, wenn ein Reparaturaufruf ein strukturiertes Ergebnis erzeugt. Überprüfen Sie data.status: failed und stale sind Reparatur-Domain-Status, keine Transportfehler.

{
	"data": {
		"status": "complete",
		"indexedSourceCount": 12,
		"failedSourceCount": 0,
		"skippedSourceCount": 0,
		"deletedSourceCount": 1,
		"collections": [
			{
				"collection": "posts",
				"status": "complete",
				"indexedSourceCount": 12,
				"failedSourceCount": 0,
				"skippedSourceCount": 0,
				"deletedSourceCount": 1,
				"lastErrorCode": null,
				"startedAt": "2026-07-07T12:00:00.000Z",
				"completedAt": "2026-07-07T12:00:01.000Z"
			}
		]
	}
}

Antwortfelder auf oberster Ebene:

FeldTypBeschreibung
statuscomplete | partial | failed | staleAggregierter Reparaturstatus
indexedSourceCountnumberWährend der Reparatur indizierte Quellen
failedSourceCountnumberWährend der Reparatur fehlgeschlagene Quellen
skippedSourceCountnumberÜbersprungene Quellen, einschließlich veralteter Konflikte
deletedSourceCountnumberWährend der Reparatur gelöschte veraltete Nutzungszeilen
collectionsarrayReparaturzusammenfassungen pro Collection

Zusammenfassungsfelder pro Collection:

FeldTypBeschreibung
collectionstringCollection-Slug
statuscomplete | partial | failed | staleCollection-Reparaturstatus
indexedSourceCountnumberFür diese Collection indizierte Quellen
failedSourceCountnumberFür diese Collection fehlgeschlagene Quellen
skippedSourceCountnumberFür diese Collection übersprungene Quellen
deletedSourceCountnumberFür diese Collection gelöschte veraltete Nutzungszeilen
lastErrorCodestring | nullLetzter Collection-Reparaturfehler, wenn verfügbar
startedAtstringStartzeitpunkt der Reparatur
completedAtstring | nullAbschlusszeit, oder null für veraltete Ergebnisse

Unbekannte Collections geben 200 mit data.status: "failed" und einem pro-Collection-lastErrorCode wie COLLECTION_NOT_FOUND zurück. Transportfehler verwenden weiterhin den Standard-Fehlerumschlag, einschließlich 400, 401, 403, 413 und 500.

Mediendatei abrufen

GET /_emdash/api/media/file/:key

Liefert den eigentlichen Dateiinhalt. Nur für lokalen Speicher.

Revisions-Endpunkte

Revisionen auflisten

GET /_emdash/api/content/:collection/:entryId/revisions

Parameter

ParameterTypBeschreibung
limitnumberMax. zurückzugebende Revisionen (Standard: 50)

Antwort

{
  "success": true,
  "data": {
    "items": [
      {
        "id": "01HXK5MZSN...",
        "collection": "posts",
        "entryId": "01HXK5MZSN...",
        "data": { ... },
        "createdAt": "2025-01-24T12:00:00Z"
      }
    ],
    "total": 5
  }
}

Revision abrufen

GET /_emdash/api/revisions/:revisionId

Revision wiederherstellen

POST /_emdash/api/revisions/:revisionId/restore

Stellt den Inhalt auf den Zustand dieser Revision wieder her und erstellt eine neue Revision.

Schema-Endpunkte

Collections auflisten

GET /_emdash/api/schema/collections

Antwort

{
	"success": true,
	"data": {
		"items": [
			{
				"id": "01HXK5MZSN...",
				"slug": "posts",
				"label": "Posts",
				"labelSingular": "Post",
				"supports": ["drafts", "revisions", "preview"]
			}
		]
	}
}

Collection abrufen

GET /_emdash/api/schema/collections/:slug

Parameter

ParameterTypBeschreibung
includeFieldsbooleanFelddefinitionen einschließen (Query)

Collection erstellen

POST /_emdash/api/schema/collections
Content-Type: application/json

Anfragekörper

{
	"slug": "products",
	"label": "Products",
	"labelSingular": "Product",
	"description": "Product catalog",
	"supports": ["drafts", "revisions"]
}

Collection aktualisieren

PUT /_emdash/api/schema/collections/:slug
Content-Type: application/json

Collection löschen

DELETE /_emdash/api/schema/collections/:slug

Parameter

ParameterTypBeschreibung
forcebooleanAuch löschen, wenn die Collection Inhalte hat (Query)

Felder auflisten

GET /_emdash/api/schema/collections/:slug/fields

Feld erstellen

POST /_emdash/api/schema/collections/:slug/fields
Content-Type: application/json

Anfragekörper

{
	"slug": "price",
	"label": "Price",
	"type": "number",
	"required": true,
	"validation": {
		"min": 0
	}
}

Feld aktualisieren

PUT /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlug
Content-Type: application/json

Feld löschen

DELETE /_emdash/api/schema/collections/:collectionSlug/fields/:fieldSlug

Felder neu sortieren

POST /_emdash/api/schema/collections/:slug/fields/reorder
Content-Type: application/json

Anfragekörper

{
	"fieldSlugs": ["title", "content", "author", "publishedAt"]
}

Schema-Export

Schema exportieren (JSON)

GET /_emdash/api/schema
Accept: application/json

Schema exportieren (TypeScript)

GET /_emdash/api/schema?format=typescript
Accept: text/typescript

Gibt TypeScript-Interfaces für alle Collections zurück.

Plugin-Endpunkte

Plugins auflisten

GET /_emdash/api/admin/plugins

Plugin abrufen

GET /_emdash/api/admin/plugins/:id

Plugin aktivieren

POST /_emdash/api/admin/plugins/:id/enable

Plugin deaktivieren

POST /_emdash/api/admin/plugins/:id/disable

Fehlercodes

CodeHTTP-StatusBeschreibung
NOT_FOUND404Ressource nicht gefunden
VALIDATION_ERROR400Ungültige Eingabedaten
UNAUTHORIZED401Fehlendes oder ungültiges Token
FORBIDDEN403Unzureichende Berechtigungen
CONTENT_LIST_ERROR500Inhalte auflisten fehlgeschlagen
CONTENT_CREATE_ERROR500Inhalt erstellen fehlgeschlagen
CONTENT_UPDATE_ERROR500Inhalt aktualisieren fehlgeschlagen
CONTENT_DELETE_ERROR500Inhalt löschen fehlgeschlagen
MEDIA_LIST_ERROR500Medien auflisten fehlgeschlagen
MEDIA_CREATE_ERROR500Medien erstellen fehlgeschlagen
SCHEMA_CREATE_ERROR500Schema-Operation fehlgeschlagen
SLUG_CONFLICT409Slug existiert bereits
RESERVED_SLUG400Slug ist reserviert

Such-Endpunkte

Globale Suche

GET /_emdash/api/search?q=hello+world

Parameter

ParameterTypBeschreibung
qstringSuchabfrage (erforderlich)
collectionsstringKommaseparierte Collection-Slugs
statusstringNach Status filtern (Standard: published)
limitnumberMax. Ergebnisse (Standard: 20)
cursorstringPaginierungs-Cursor

Antwort

{
  "success": true,
  "data": {
    "items": [
      {
        "collection": "posts",
        "id": "01HXK5MZSN...",
        "slug": "hello-world",
        "locale": "en",
        "title": "Hello World",
        "snippet": "...this is a <mark>hello</mark> <mark>world</mark> example...",
        "score": 0.95
      }
    ],
    "nextCursor": "eyJvZmZzZXQiOjIwfQ"
  }
}

Suchvorschläge

GET /_emdash/api/search/suggest?q=hel&limit=5

Gibt präfixübereinstimmende Titel für die Autovervollständigung zurück.

Suchindex neu erstellen

POST /_emdash/api/search/rebuild

FTS-Index für alle oder bestimmte Collections neu erstellen.

Suchstatistiken

GET /_emdash/api/search/stats

Gibt die Anzahl indizierter Dokumente pro Collection zurück.

Abschnitts-Endpunkte

Abschnitte auflisten

GET /_emdash/api/sections
GET /_emdash/api/sections?source=theme
GET /_emdash/api/sections?search=newsletter

Abschnitt abrufen

GET /_emdash/api/sections/:slug

Abschnitt erstellen

POST /_emdash/api/sections
Content-Type: application/json

{
  "slug": "my-section",
  "title": "My Section",
  "keywords": ["keyword1"],
  "content": [...]
}

Abschnitt aktualisieren

PUT /_emdash/api/sections/:slug

Abschnitt löschen

DELETE /_emdash/api/sections/:slug

Einstellungs-Endpunkte

Alle Einstellungen abrufen

GET /_emdash/api/settings

Einstellungen aktualisieren

POST /_emdash/api/settings
Content-Type: application/json

{
  "siteTitle": "My Site",
  "tagline": "A great site",
  "postsPerPage": 10
}

Menü-Endpunkte

Menüs auflisten

GET /_emdash/api/menus

Menü abrufen

GET /_emdash/api/menus/:name

Menü erstellen

POST /_emdash/api/menus
Content-Type: application/json

{
  "name": "main",
  "label": "Main Navigation",
  "items": []
}

Menü aktualisieren

PUT /_emdash/api/menus/:name

Menü löschen

DELETE /_emdash/api/menus/:name

Menüeintrag hinzufügen

POST /_emdash/api/menus/:name/items
Content-Type: application/json

{
  "label": "About",
  "url": "/about",
  "position": 0
}

Menüeinträge neu sortieren

POST /_emdash/api/menus/:name/reorder
Content-Type: application/json

{
  "itemIds": ["item_1", "item_2", "item_3"]
}

Taxonomie-Endpunkte

Taxonomie-Definitionen auflisten

GET /_emdash/api/taxonomies

Taxonomie erstellen

POST /_emdash/api/taxonomies
Content-Type: application/json

{
  "name": "categories",
  "label": "Categories",
  "hierarchical": true,
  "collections": ["posts"]
}

Begriffe auflisten

GET /_emdash/api/taxonomies/:name/terms

Begriff erstellen

POST /_emdash/api/taxonomies/:name/terms
Content-Type: application/json

{
  "slug": "tutorials",
  "label": "Tutorials",
  "parentId": "term_abc",
  "description": "How-to guides"
}

Begriff aktualisieren

PUT /_emdash/api/taxonomies/:name/terms/:slug

Begriff löschen

DELETE /_emdash/api/taxonomies/:name/terms/:slug

Eintragsbegriffe setzen

POST /_emdash/api/content/:collection/:id/terms/:taxonomy
Content-Type: application/json

{
  "termIds": ["term_news", "term_featured"]
}

Widget-Bereich-Endpunkte

Widget-Bereiche auflisten

GET /_emdash/api/widget-areas

Widget-Bereich abrufen

GET /_emdash/api/widget-areas/:name

Widget-Bereich erstellen

POST /_emdash/api/widget-areas
Content-Type: application/json

{
  "name": "sidebar",
  "label": "Main Sidebar",
  "description": "Appears on posts"
}

Widget-Bereich löschen

DELETE /_emdash/api/widget-areas/:name

Widget hinzufügen

POST /_emdash/api/widget-areas/:name/widgets
Content-Type: application/json

{
  "type": "content",
  "title": "About",
  "content": [...]
}

Widget aktualisieren

PUT /_emdash/api/widget-areas/:name/widgets/:id

Widget löschen

DELETE /_emdash/api/widget-areas/:name/widgets/:id

Widgets neu sortieren

POST /_emdash/api/widget-areas/:name/reorder
Content-Type: application/json

{
  "widgetIds": ["widget_1", "widget_2", "widget_3"]
}

Benutzerverwaltungs-Endpunkte

Benutzer auflisten

GET /_emdash/api/admin/users
GET /_emdash/api/admin/users?role=40
GET /_emdash/api/admin/users?search=john

Benutzer abrufen

GET /_emdash/api/admin/users/:id

Benutzer aktualisieren

PUT /_emdash/api/admin/users/:id
Content-Type: application/json

{
  "name": "John Doe",
  "role": 40
}

Benutzer aktivieren

POST /_emdash/api/admin/users/:id/enable

Benutzer deaktivieren

POST /_emdash/api/admin/users/:id/disable

Authentifizierungs-Endpunkte

Setup-Status

GET /_emdash/api/setup/status

Gibt zurück, ob das Setup abgeschlossen ist und ob Benutzer existieren.

Passkey-Anmeldung

POST /_emdash/api/auth/passkey/options

WebAuthn-Authentifizierungsoptionen abrufen.

POST /_emdash/api/auth/passkey/verify
Content-Type: application/json

{
  "id": "credential-id",
  "rawId": "...",
  "response": {...},
  "type": "public-key"
}

Passkey verifizieren und Sitzung erstellen.

POST /_emdash/api/auth/magic-link/send
Content-Type: application/json

{
  "email": "[email protected]"
}
GET /_emdash/api/auth/magic-link/verify?token=xxx

Abmelden

POST /_emdash/api/auth/logout

Aktueller Benutzer

GET /_emdash/api/auth/me

Benutzer einladen

POST /_emdash/api/auth/invite
Content-Type: application/json

{
  "email": "[email protected]",
  "role": 30
}

Passkey-Verwaltung

GET /_emdash/api/auth/passkey

Passkeys des Benutzers auflisten.

POST /_emdash/api/auth/passkey/register/options
POST /_emdash/api/auth/passkey/register/verify

Neuen Passkey registrieren.

PATCH /_emdash/api/auth/passkey/:id
Content-Type: application/json

{
  "name": "MacBook Pro"
}

Passkey umbenennen.

DELETE /_emdash/api/auth/passkey/:id

Passkey löschen.

Import-Endpunkte

WordPress-Export analysieren

POST /_emdash/api/import/wordpress/analyze
Content-Type: multipart/form-data

file: <WXR file>

WordPress-Import ausführen

POST /_emdash/api/import/wordpress/execute
Content-Type: application/json

{
  "analysisId": "...",
  "options": {
    "includeMedia": true,
    "includeTaxonomies": true,
    "includeMenus": true
  }
}

Ratenbegrenzung

API-Endpunkte können je nach Deployment-Konfiguration ratenbegrenzt sein. Bei Ratenbegrenzung enthalten die Antworten:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

CORS

Die API unterstützt CORS für Browser-Anfragen. Konfigurieren Sie erlaubte Origins in Ihrem Deployment.