Référence de l'API REST

Sur cette page

EmDash expose une API REST à /_emdash/api/ pour la gestion de contenu, l’upload de médias et les opérations de schéma.

Authentification

Les requêtes API nécessitent une authentification via un token Bearer dans l’en-tête Authorization :

Authorization: Bearer <token>

Générez des tokens via l’interface d’administration ou de manière programmatique.

Format de réponse

Toutes les réponses suivent un format cohérent. Une réponse réussie enveloppe le résultat dans data :

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

Une réponse d’erreur inclut un code, un message et des détails optionnels :

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

Points de terminaison de contenu

Lister le contenu

GET /_emdash/api/content/:collection

Paramètres

ParamètreTypeDescription
collectionstringSlug de la collection (chemin)
cursorstringCurseur de pagination (query)
limitnumberÉléments par page (query, par défaut : 50)
statusstringFiltrer par statut (query)
orderBystringChamp de tri (query)
orderstringDirection du tri : asc ou desc (query)

Réponse

{
  "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..."
  }
}

Obtenir du contenu

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

Réponse

{
  "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"
    }
  }
}

Créer du contenu

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

Corps de la requête

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

Réponse

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

Mettre à jour le contenu

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

Corps de la requête

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

Supprimer du contenu

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

Réponse

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

Points de terminaison des médias

Lister les médias

GET /_emdash/api/media?includeUsage=1

Paramètres

ParamètreTypeDescription
cursorstringCurseur de pagination opaque
limitnumberÉléments par page, de 1 à 100 (par défaut : 50)
mimeTypestringFiltrer par un ou plusieurs types MIME séparés par des virgules
qstringRecherche de nom de fichier insensible à la casse
includeUsage1Inclure un résumé d’usage avec couverture sur chaque élément retourné

Réponse

{
	"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..."
	}
}

Obtenir un média

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

includeUsage est optionnel pour la liste et l’obtention. Sa seule valeur acceptée est 1. Lorsqu’il est omis, la propriété usage est omise et le serveur n’exécute pas de requêtes d’utilisation.

Résumés d’utilisation

usage.count est le nombre de lignes de contenu ou de locales actives distinctes d’EmDash dont la source indexée actuelle sélectionnée référence l’élément média. Les références répétées et les multiples variantes de source pour la même entrée de contenu comptent une fois. Le contenu dans la corbeille ne compte pas.

Un comptage numérique peut révéler du contenu de type brouillon. Il n’est retourné que lorsqu’un utilisateur de session a content:read_drafts, ou lorsqu’un token API a le scope admin et que son utilisateur associé a également cette permission. Les autres lecteurs de médias reçoivent usage.count: null ; c’est une réponse expurgée réussie, pas une erreur.

Chaque résumé demandé inclut une couverture agrégée pour toutes les collections de contenu actuellement enregistrées :

StatutSignification
completeChaque collection enregistrée a une couverture d’utilisation actuelle et complétée
neverAucune collection enregistrée n’a terminé une réparation d’utilisation initiale
runningUne réparation d’utilisation est actuellement en cours
partialLa couverture est mixte ou seule une partie du périmètre enregistré a été indexée
failedLa couverture a échoué sur l’ensemble du périmètre enregistré
staleLa couverture indexée est obsolète
unknownLa couverture stockée contient un état que cette version ne reconnaît pas

Seul complete supporte une déclaration de zéro complet avec périmètre dans les champs gérés par EmDash décrits ci-dessous. Les comptages avec tout autre statut sont des projections indexées et peuvent sur-déclarer ou sous-déclarer. Même les résultats complets sont consultatifs pendant les écritures concurrentes ; les lectures d’utilisation ne sont pas un verrou transactionnel et ne doivent pas être utilisées comme garantie de suppression.

Obtenir les détails d’utilisation des médias

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

Ce point de terminaison nécessite media:read et content:read_drafts. Les appelants authentifiés par token nécessitent également le scope admin ; le scope du token ne contourne pas les permissions de l’utilisateur associé.

limit contrôle les groupes d’entrées de contenu par page, de 1 à 100 (par défaut : 50). La pagination ne divise jamais les sources ou occurrences pour un groupe d’entrées retourné.

{
	"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"
		}
	}
}

Les détails autorisés incluent les entrées actives et supprimées. Un deletedAt non nul identifie une entrée dans la corbeille. Les sources sont columns ou draft_overlay ; les occurrences identifient le champ supporté et le chemin sans exposer les métadonnées internes de l’index.

L’utilisation des médias couvre les références de médias locaux dans les champs d’image et de fichier de niveau supérieur, les champs d’image de répéteur et les blocs d’image Portable Text gérés par les collections de contenu EmDash. Elle ne scanne pas le code personnalisé, le HTML rendu, les paramètres, les menus, les widgets, les données privées des plugins, les sites externes ou les actifs exclusifs au fournisseur.

Créer un média

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

Corps de la requête

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

Mettre à jour un média

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

Corps de la requête

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

Supprimer un média

DELETE /_emdash/api/media/:id

Réparer l’utilisation des médias

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

Répare l’index d’utilisation des médias de contenu pour une collection ou pour toutes les collections de contenu. C’est un point de terminaison administrateur/opérateur : les appelants authentifiés par session ont besoin de schema:manage, et les tokens Bearer doivent avoir le scope admin car la route est sous /_emdash/api/admin.

La réparation de tout le contenu s’exécute de manière synchrone et séquentielle dans la version actuelle. Elle peut être coûteuse sur les grands sites, les appelants doivent donc la déclencher délibérément et attendre la réponse.

Corps de la requête

Réparer une collection :

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

Réparer toutes les collections de contenu :

{
	"scope": "all"
}

Le corps de la requête est obligatoire. Les slugs invalides, les clés de requête inconnues, le scope manquant et les requêtes sans corps retournent 400 au lieu de réparer tout le contenu par défaut.

Réponse

Le point de terminaison retourne 200 lorsqu’une invocation de réparation produit un résultat structuré. Inspectez data.status : failed et stale sont des statuts du domaine de réparation, pas des erreurs de transport.

{
	"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"
			}
		]
	}
}

Champs de réponse de niveau supérieur :

ChampTypeDescription
statuscomplete | partial | failed | staleStatut de réparation agrégé
indexedSourceCountnumberSources indexées pendant la réparation
failedSourceCountnumberSources ayant échoué pendant la réparation
skippedSourceCountnumberSources ignorées, y compris les conflits obsolètes
deletedSourceCountnumberLignes d’utilisation obsolètes supprimées pendant la réparation
collectionsarrayRésumés de réparation par collection

Champs de résumé par collection :

ChampTypeDescription
collectionstringSlug de la collection
statuscomplete | partial | failed | staleStatut de réparation de la collection
indexedSourceCountnumberSources indexées pour cette collection
failedSourceCountnumberSources ayant échoué pour cette collection
skippedSourceCountnumberSources ignorées pour cette collection
deletedSourceCountnumberLignes d’utilisation obsolètes supprimées pour cette collection
lastErrorCodestring | nullDernière erreur de réparation de collection, si disponible
startedAtstringHeure de début de la réparation
completedAtstring | nullHeure de fin, ou null pour les résultats obsolètes

Les collections inconnues retournent 200 avec data.status: "failed" et un lastErrorCode par collection tel que COLLECTION_NOT_FOUND. Les erreurs de transport utilisent toujours l’enveloppe d’erreur standard, y compris 400, 401, 403, 413 et 500.

Obtenir un fichier média

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

Sert le contenu réel du fichier. Pour le stockage local uniquement.

Points de terminaison des révisions

Lister les révisions

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

Paramètres

ParamètreTypeDescription
limitnumberMax. de révisions à retourner (par défaut : 50)

Réponse

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

Obtenir une révision

GET /_emdash/api/revisions/:revisionId

Restaurer une révision

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

Restaure le contenu à l’état de cette révision et crée une nouvelle révision.

Points de terminaison du schéma

Lister les collections

GET /_emdash/api/schema/collections

Réponse

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

Obtenir une collection

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

Paramètres

ParamètreTypeDescription
includeFieldsbooleanInclure les définitions de champs (query)

Créer une collection

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

Corps de la requête

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

Mettre à jour une collection

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

Supprimer une collection

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

Paramètres

ParamètreTypeDescription
forcebooleanSupprimer même si la collection a du contenu (query)

Lister les champs

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

Créer un champ

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

Corps de la requête

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

Mettre à jour un champ

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

Supprimer un champ

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

Réordonner les champs

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

Corps de la requête

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

Export de schéma

Exporter le schéma (JSON)

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

Exporter le schéma (TypeScript)

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

Retourne des interfaces TypeScript pour toutes les collections.

Points de terminaison des plugins

Lister les plugins

GET /_emdash/api/admin/plugins

Obtenir un plugin

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

Activer un plugin

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

Désactiver un plugin

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

Codes d’erreur

CodeStatut HTTPDescription
NOT_FOUND404Ressource non trouvée
VALIDATION_ERROR400Données d’entrée invalides
UNAUTHORIZED401Token manquant ou invalide
FORBIDDEN403Permissions insuffisantes
CONTENT_LIST_ERROR500Échec de la liste du contenu
CONTENT_CREATE_ERROR500Échec de la création du contenu
CONTENT_UPDATE_ERROR500Échec de la mise à jour du contenu
CONTENT_DELETE_ERROR500Échec de la suppression du contenu
MEDIA_LIST_ERROR500Échec de la liste des médias
MEDIA_CREATE_ERROR500Échec de la création du média
SCHEMA_CREATE_ERROR500Opération de schéma échouée
SLUG_CONFLICT409Le slug existe déjà
RESERVED_SLUG400Le slug est réservé

Points de terminaison de recherche

Recherche globale

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

Paramètres

ParamètreTypeDescription
qstringRequête de recherche (obligatoire)
collectionsstringSlugs de collections séparés par des virgules
statusstringFiltrer par statut (par défaut : published)
limitnumberMax. de résultats (par défaut : 20)
cursorstringCurseur de pagination

Réponse

{
  "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"
  }
}

Suggestions de recherche

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

Retourne des titres avec correspondance de préfixe pour l’autocomplétion.

Reconstruire l’index de recherche

POST /_emdash/api/search/rebuild

Reconstruire l’index FTS pour toutes ou certaines collections.

Statistiques de recherche

GET /_emdash/api/search/stats

Retourne le nombre de documents indexés par collection.

Points de terminaison des sections

Lister les sections

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

Obtenir une section

GET /_emdash/api/sections/:slug

Créer une section

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

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

Mettre à jour une section

PUT /_emdash/api/sections/:slug

Supprimer une section

DELETE /_emdash/api/sections/:slug

Points de terminaison des paramètres

Obtenir tous les paramètres

GET /_emdash/api/settings

Mettre à jour les paramètres

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

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

Points de terminaison des menus

Lister les menus

GET /_emdash/api/menus

Obtenir un menu

GET /_emdash/api/menus/:name

Créer un menu

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

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

Mettre à jour un menu

PUT /_emdash/api/menus/:name

Supprimer un menu

DELETE /_emdash/api/menus/:name

Ajouter un élément de menu

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

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

Réordonner les éléments de menu

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

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

Points de terminaison des taxonomies

Lister les définitions de taxonomies

GET /_emdash/api/taxonomies

Créer une taxonomie

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

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

Lister les termes

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

Créer un terme

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

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

Mettre à jour un terme

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

Supprimer un terme

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

Définir les termes d’une entrée

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

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

Points de terminaison des zones de widgets

Lister les zones de widgets

GET /_emdash/api/widget-areas

Obtenir une zone de widgets

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

Créer une zone de widgets

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

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

Supprimer une zone de widgets

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

Ajouter un widget

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

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

Mettre à jour un widget

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

Supprimer un widget

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

Réordonner les widgets

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

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

Points de terminaison de gestion des utilisateurs

Lister les utilisateurs

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

Obtenir un utilisateur

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

Mettre à jour un utilisateur

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

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

Activer un utilisateur

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

Désactiver un utilisateur

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

Points de terminaison d’authentification

Statut de configuration

GET /_emdash/api/setup/status

Retourne si la configuration est terminée et si des utilisateurs existent.

Connexion par Passkey

POST /_emdash/api/auth/passkey/options

Obtenir les options d’authentification WebAuthn.

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

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

Vérifier le passkey et créer une session.

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

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

Déconnexion

POST /_emdash/api/auth/logout

Utilisateur actuel

GET /_emdash/api/auth/me

Inviter un utilisateur

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

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

Gestion des Passkeys

GET /_emdash/api/auth/passkey

Lister les passkeys de l’utilisateur.

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

Enregistrer un nouveau passkey.

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

{
  "name": "MacBook Pro"
}

Renommer un passkey.

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

Supprimer un passkey.

Points de terminaison d’importation

Analyser l’export WordPress

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

file: <WXR file>

Exécuter l’importation WordPress

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

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

Limitation de débit

Les points de terminaison API peuvent être limités en débit selon la configuration du déploiement. Lors d’une limitation de débit, les réponses incluent :

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

CORS

L’API supporte CORS pour les requêtes navigateur. Configurez les origines autorisées dans votre déploiement.