EmDash expose son interface de programmation d’applications (API) prise en charge sous /_emdash/api/. Utilisez le document OpenAPI 3.1 généré pour les paramètres de requête, les corps, les schémas de réponse, les codes d’état et la génération de clients :
GET /_emdash/api/openapi.json
Le document est généré à partir des mêmes schémas Zod que ceux utilisés par l’API. Il reflète aussi la taille maximale configurée pour le téléversement de médias.
Limite du contrat public
Le document OpenAPI délimite l’API REST prise en charge. EmDash dispose aussi de routes pour son interface d’administration et les flux de protocole. Une route présente dans l’arborescence source mais absente d’OpenAPI n’est pas une opération REST prise en charge pour les clients externes.
Cette distinction s’applique aux routes de sauvegarde, d’administration des bylines, de parcours des relations, de gestion des plugins, de configuration initiale, d’importation et d’authentification. Utilisez le guide des sauvegardes pour les backups et les outils MCP byline pour la gestion des bylines prise en charge. Les points de terminaison OAuth sont des points de protocole ; découvrez-les à partir des métadonnées décrites dans la section OAuth MCP plutôt que de les traiter comme des points de terminaison REST applicatifs.
Authentification et autorisation
La plupart des opérations acceptent soit un cookie de session EmDash, soit un jeton Bearer. Envoyez un jeton d’accès personnel ou un jeton d’accès OAuth dans l’en-tête Authorization :
Authorization: Bearer $EMDASH_TOKEN
Les jetons Bearer sont limités par leurs scopes et le rôle de l’utilisateur associé. Les requêtes par session utilisent le rôle de l’utilisateur. Consultez rôles utilisateur et scopes de jeton pour le modèle d’autorisation.
GET et POST /_emdash/api/comments/{collection}/{contentId} sont publics. L’opération GET renvoie les commentaires approuvés ; l’opération POST soumet un commentaire à modération. Les autres opérations de modération de commentaires exigent une authentification.
Protection contre la falsification de requêtes intersites
Pour une requête modifiant l’état et authentifiée par un cookie de session, incluez cet en-tête :
X-EmDash-Request: 1
Les requêtes avec jeton Bearer n’exigent pas l’en-tête car elles n’utilisent pas les identifiants ambient du navigateur. Les requêtes navigateur vers une opération d’écriture publique doivent soit envoyer l’en-tête, soit avoir un Origin correspondant à l’origine publique ou de requête du site EmDash.
Enveloppes de réponse
Une réponse JSON réussie définit success à true et place le résultat propre à l’opération dans data :
{
"success": true,
"data": {
"items": []
}
}
Une erreur définit success à false et inclut un code stable lisible par machine et un message. Certaines erreurs incluent aussi des details structurés :
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Content item not found"
}
}
Utilisez les codes d’état et les schémas d’erreur de chaque opération OpenAPI. Les statuts courants sont 400 pour une entrée invalide, 401 pour des identifiants manquants ou invalides, 403 pour un scope ou une permission insuffisants, 404 pour une ressource absente, 409 pour un conflit d’état, 413 pour un téléversement trop volumineux, 422 lorsqu’un plugin rejette l’enregistrement, et 500 pour une défaillance interne.
Inventaire des points de terminaison
L’identifiant d’opération est stable dans le contrat généré et sert souvent de nom de méthode aux générateurs de clients OpenAPI. L’inventaire suivant est vérifié par rapport au document OpenAPI généré.
Contenu
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/content/{collection} | listContent | Lister les éléments de contenu |
POST | /_emdash/api/content/{collection} | createContent | Créer un élément de contenu |
GET | /_emdash/api/content/{collection}/{id} | getContent | Obtenir un élément de contenu |
PUT | /_emdash/api/content/{collection}/{id} | updateContent | Mettre à jour un élément de contenu |
DELETE | /_emdash/api/content/{collection}/{id} | deleteContent | Supprimer un élément de contenu (suppression logique) |
POST | /_emdash/api/content/{collection}/{id}/publish | publishContent | Publier un élément de contenu |
POST | /_emdash/api/content/{collection}/{id}/unpublish | unpublishContent | Dépublier un élément de contenu |
POST | /_emdash/api/content/{collection}/{id}/schedule | scheduleContent | Planifier la publication future d’un contenu |
DELETE | /_emdash/api/content/{collection}/{id}/schedule | unscheduleContent | Annuler la publication planifiée |
POST | /_emdash/api/content/{collection}/{id}/duplicate | duplicateContent | Dupliquer un élément de contenu |
POST | /_emdash/api/content/{collection}/{id}/restore | restoreContent | Restaurer un élément de contenu depuis la corbeille |
DELETE | /_emdash/api/content/{collection}/{id}/permanent | permanentDeleteContent | Supprimer définitivement un élément de contenu |
GET | /_emdash/api/content/{collection}/{id}/compare | compareContent | Comparer les révisions publiées et brouillon |
POST | /_emdash/api/content/{collection}/{id}/discard-draft | discardDraft | Abandonner les modifications du brouillon |
GET | /_emdash/api/content/{collection}/{id}/lock | getEntryLock | Lire le verrou d’édition de l’entrée |
POST | /_emdash/api/content/{collection}/{id}/lock | acquireEntryLock | Prendre ou renouveler le verrou d’édition de l’entrée |
DELETE | /_emdash/api/content/{collection}/{id}/lock | releaseEntryLock | Libérer le verrou d’édition de l’appelant |
GET | /_emdash/api/content/{collection}/{id}/translations | getContentTranslations | Obtenir les traductions d’un élément de contenu |
GET | /_emdash/api/content/{collection}/{id}/terms/{taxonomy} | getContentTerms | Obtenir les termes de taxonomie assignés à un élément |
POST | /_emdash/api/content/{collection}/{id}/terms/{taxonomy} | setContentTerms | Définir les termes de taxonomie sur un élément |
GET | /_emdash/api/content/{collection}/authors | listContentAuthors | Lister les auteurs distincts du contenu d’une collection |
GET | /_emdash/api/content/{collection}/trash | listTrashedContent | Lister les éléments de contenu en corbeille |
Médias
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/media | listMedia | Lister les éléments médias |
POST | /_emdash/api/media | uploadMedia | Téléverser un élément média |
GET | /_emdash/api/media/folders | listMediaFolders | Lister les dossiers médias |
POST | /_emdash/api/media/folders | createMediaFolder | Créer un dossier média |
GET | /_emdash/api/media/folders/{id} | getMediaFolder | Obtenir un dossier média |
PUT | /_emdash/api/media/folders/{id} | updateMediaFolder | Mettre à jour un dossier média |
DELETE | /_emdash/api/media/folders/{id} | deleteMediaFolder | Supprimer un dossier média |
GET | /_emdash/api/media/{id} | getMedia | Obtenir un élément média |
PUT | /_emdash/api/media/{id} | updateMedia | Mettre à jour les métadonnées média |
DELETE | /_emdash/api/media/{id} | deleteMedia | Supprimer un élément média |
GET | /_emdash/api/media/{id}/usage | getMediaUsage | Obtenir les détails d’utilisation média |
PUT | /_emdash/api/media/{id}/replace | replaceMediaImage | Remplacer une image média |
POST | /_emdash/api/admin/media-usage/repair | repairMediaUsage | Réparer les index d’utilisation média |
GET | /_emdash/api/admin/media-usage/progress | getMediaUsageProgress | Obtenir la progression de l’indexation d’utilisation média |
POST | /_emdash/api/admin/media-usage/progress | advanceMediaUsageProgress | Faire avancer l’indexation d’utilisation média |
GET | /_emdash/api/admin/media-usage/work | listMediaUsageWork | Lister le travail durable d’utilisation média |
GET | /_emdash/api/admin/media-usage/activation | getMediaUsageActivation | Obtenir l’état d’activation de l’utilisation média |
POST | /_emdash/api/admin/media-usage/activation | advanceMediaUsageActivation | Faire avancer l’activation de l’utilisation média |
POST | /_emdash/api/admin/media-usage/work/retry | retryMediaUsageWork | Réessayer un travail durable d’utilisation média |
GET | /_emdash/api/admin/media-usage/collection-deletions | listMediaUsageCollectionDeletions | Lister les suppressions durables de collections |
POST | /_emdash/api/admin/media-usage/collection-deletions/retry | retryMediaUsageCollectionDeletion | Réessayer une suppression de collection |
POST | /_emdash/api/media/upload-url | getMediaUploadUrl | Obtenir une cible de téléversement média |
POST | /_emdash/api/media/{id}/confirm | confirmMediaUpload | Confirmer un téléversement média |
PUT | /_emdash/api/media/{id}/upload | uploadPendingMedia | Téléverser un fichier média en attente via EmDash |
Schéma
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/schema/block-types | listBlockTypes | Lister les types de bloc |
POST | /_emdash/api/schema/block-types | createBlockType | Créer un type de bloc |
GET | /_emdash/api/schema/block-types/{slug} | getBlockType | Obtenir un type de bloc |
PUT | /_emdash/api/schema/block-types/{slug} | updateBlockType | Mettre à jour un type de bloc |
POST | /_emdash/api/schema/block-types/{slug}/versions/{version}/activate | activateBlockTypeVersion | Activer une version de type de bloc |
GET | /_emdash/api/schema/collections | listCollections | Lister toutes les collections |
POST | /_emdash/api/schema/collections | createCollection | Créer une collection |
GET | /_emdash/api/schema/collections/{slug} | getCollection | Obtenir une collection |
PUT | /_emdash/api/schema/collections/{slug} | updateCollection | Mettre à jour une collection |
DELETE | /_emdash/api/schema/collections/{slug} | deleteCollection | Supprimer une collection |
GET | /_emdash/api/schema/collections/{slug}/fields | listFields | Lister les champs d’une collection |
POST | /_emdash/api/schema/collections/{slug}/fields | createField | Créer un champ |
GET | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | getField | Obtenir un champ |
PUT | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | updateField | Mettre à jour un champ |
DELETE | /_emdash/api/schema/collections/{slug}/fields/{fieldSlug} | deleteField | Supprimer un champ |
POST | /_emdash/api/schema/collections/reorder | reorderCollections | Réordonner les collections dans la barre latérale admin |
POST | /_emdash/api/schema/collections/{slug}/fields/reorder | reorderFields | Réordonner les champs d’une collection |
GET | /_emdash/api/schema/orphans | listOrphanedTables | Lister les tables de contenu orphelines |
POST | /_emdash/api/schema/orphans/{slug} | registerOrphanedTable | Enregistrer une table orpheline comme collection |
Commentaires
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/comments/{collection}/{contentId} | listPublicComments | Lister les commentaires approuvés du contenu |
POST | /_emdash/api/comments/{collection}/{contentId} | createComment | Soumettre un nouveau commentaire |
GET | /_emdash/api/admin/comments | listAdminComments | Lister les commentaires à modérer |
GET | /_emdash/api/admin/comments/counts | getCommentCounts | Obtenir les comptages par statut de commentaire |
POST | /_emdash/api/admin/comments/bulk | bulkCommentAction | Approuver, marquer spam, corbeille ou supprimer des commentaires en lot |
GET | /_emdash/api/admin/comments/{id} | getComment | Obtenir un commentaire |
DELETE | /_emdash/api/admin/comments/{id} | deleteComment | Supprimer définitivement un commentaire |
PUT | /_emdash/api/admin/comments/{id}/status | updateCommentStatus | Changer le statut d’un commentaire |
Taxonomies
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/taxonomies | listTaxonomies | Lister toutes les définitions de taxonomie |
GET | /_emdash/api/taxonomies/{name} | getTaxonomy | Obtenir une définition de taxonomie |
PUT | /_emdash/api/taxonomies/{name} | updateTaxonomy | Mettre à jour une définition de taxonomie |
DELETE | /_emdash/api/taxonomies/{name} | deleteTaxonomy | Supprimer une taxonomie, ses termes et leurs assignations au contenu |
GET | /_emdash/api/taxonomies/{name}/translations | listTaxonomyTranslations | Lister chaque variante de locale d’une définition de taxonomie |
POST | /_emdash/api/taxonomies/{name}/reorder | reorderTerms | Définir l’ordre manuel d’un groupe de termes frères |
GET | /_emdash/api/taxonomies/{name}/terms | listTerms | Lister les termes d’une taxonomie |
POST | /_emdash/api/taxonomies/{name}/terms | createTerm | Créer un terme |
GET | /_emdash/api/taxonomies/{name}/terms/{slug} | getTerm | Obtenir un terme par slug |
PUT | /_emdash/api/taxonomies/{name}/terms/{slug} | updateTerm | Mettre à jour un terme |
DELETE | /_emdash/api/taxonomies/{name}/terms/{slug} | deleteTerm | Supprimer un terme |
Menus
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/menus | listMenus | Lister tous les menus avec le nombre d’éléments |
POST | /_emdash/api/menus | createMenu | Créer un menu |
GET | /_emdash/api/menus/{name} | getMenu | Obtenir un menu avec tous ses éléments |
PUT | /_emdash/api/menus/{name} | updateMenu | Mettre à jour un menu |
DELETE | /_emdash/api/menus/{name} | deleteMenu | Supprimer un menu et ses éléments |
POST | /_emdash/api/menus/{name}/items | createMenuItem | Ajouter un élément à un menu |
PUT | /_emdash/api/menus/{name}/items/{id} | updateMenuItem | Mettre à jour un élément de menu |
DELETE | /_emdash/api/menus/{name}/items/{id} | deleteMenuItem | Supprimer un élément de menu |
POST | /_emdash/api/menus/{name}/reorder | reorderMenuItems | Réordonner les éléments de menu par lot |
Sections
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/sections | listSections | Lister les sections |
POST | /_emdash/api/sections | createSection | Créer une section |
GET | /_emdash/api/sections/{slug} | getSection | Obtenir une section par slug |
PUT | /_emdash/api/sections/{slug} | updateSection | Mettre à jour une section |
DELETE | /_emdash/api/sections/{slug} | deleteSection | Supprimer une section |
Widgets
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/widget-areas | listWidgetAreas | Lister toutes les zones de widgets |
POST | /_emdash/api/widget-areas | createWidgetArea | Créer une zone de widgets |
GET | /_emdash/api/widget-areas/{name} | getWidgetArea | Obtenir une zone de widgets avec ses widgets |
DELETE | /_emdash/api/widget-areas/{name} | deleteWidgetArea | Supprimer une zone de widgets et ses widgets |
POST | /_emdash/api/widget-areas/{name}/widgets | createWidget | Ajouter un widget à une zone |
PUT | /_emdash/api/widget-areas/{name}/widgets/{id} | updateWidget | Mettre à jour un widget |
DELETE | /_emdash/api/widget-areas/{name}/widgets/{id} | deleteWidget | Supprimer un widget |
POST | /_emdash/api/widget-areas/{name}/reorder | reorderWidgets | Réordonner les widgets dans une zone |
Paramètres
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/settings | getSettings | Obtenir les paramètres du site |
PUT | /_emdash/api/settings | updateSettings | Mettre à jour les paramètres du site |
Recherche
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/search | search | Recherche full-text dans les collections |
GET | /_emdash/api/search/suggest | searchSuggest | Suggestions de recherche en autocomplétion |
POST | /_emdash/api/search/rebuild | rebuildSearchIndex | Reconstruire l’index de recherche d’une collection |
POST | /_emdash/api/search/enable | enableSearch | Activer ou désactiver la recherche pour une collection |
GET | /_emdash/api/search/stats | getSearchStats | Obtenir les statistiques de l’index de recherche |
Redirections
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/redirects | listRedirects | Lister les redirections |
POST | /_emdash/api/redirects | createRedirect | Créer une règle de redirection |
GET | /_emdash/api/redirects/{id} | getRedirect | Obtenir une redirection |
PUT | /_emdash/api/redirects/{id} | updateRedirect | Mettre à jour une redirection |
DELETE | /_emdash/api/redirects/{id} | deleteRedirect | Supprimer une redirection |
GET | /_emdash/api/redirects/404s | listNotFoundEntries | Lister les entrées du journal 404 |
POST | /_emdash/api/redirects/404s | pruneNotFoundLog | Élaguer les anciennes entrées du journal 404 |
DELETE | /_emdash/api/redirects/404s | clearNotFoundLog | Effacer toutes les entrées du journal 404 |
GET | /_emdash/api/redirects/404s/summary | getNotFoundSummary | Obtenir un résumé 404 groupé par chemin |
Utilisateurs
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/admin/users | listUsers | Lister les utilisateurs |
GET | /_emdash/api/admin/users/{id} | getUser | Obtenir les détails d’un utilisateur |
PUT | /_emdash/api/admin/users/{id} | updateUser | Mettre à jour un utilisateur |
POST | /_emdash/api/admin/users/{id}/disable | disableUser | Désactiver un compte utilisateur |
POST | /_emdash/api/admin/users/{id}/enable | enableUser | Activer un compte utilisateur |
GET | /_emdash/api/admin/allowed-domains | listAllowedDomains | Lister les domaines e-mail autorisés |
POST | /_emdash/api/admin/allowed-domains | createAllowedDomain | Ajouter un domaine e-mail autorisé |
PUT | /_emdash/api/admin/allowed-domains/{domain} | updateAllowedDomain | Mettre à jour un domaine autorisé |
DELETE | /_emdash/api/admin/allowed-domains/{domain} | deleteAllowedDomain | Retirer un domaine autorisé |
Transfert
| Méthode | Chemin | Opération | Résumé |
|---|---|---|---|
GET | /_emdash/api/admin/transfer/capabilities | getTransferCapabilities | Obtenir les capacités de transfert du site |
GET | /_emdash/api/admin/transfer/imports | listTransferImports | Lister les importations de site |
POST | /_emdash/api/admin/transfer/imports | createTransferImport | Créer une importation de site |
GET | /_emdash/api/admin/transfer/imports/{id} | getTransferImport | Obtenir une importation de site |
GET | /_emdash/api/admin/transfer/imports/{id}/missing | listTransferImportMissingFiles | Lister les fichiers du paquet restant à téléverser |
PUT | /_emdash/api/admin/transfer/imports/{id}/files/{path} | uploadTransferImportFile | Téléverser un fichier du paquet |
POST | /_emdash/api/admin/transfer/imports/{id}/analyze | analyzeTransferImport | Faire avancer l’analyse d’importation |
GET | /_emdash/api/admin/transfer/imports/{id}/plan | getTransferImportPlan | Obtenir un plan d’importation |
POST | /_emdash/api/admin/transfer/imports/{id}/cancel | cancelTransferImport | Annuler une importation de site |
POST | /_emdash/api/admin/transfer/imports/{id}/abandon | abandonTransferImport | Abandonner une importation échouée ou annulée |
POST | /_emdash/api/admin/transfer/imports/{id}/execute | executeTransferImport | Démarrer une importation planifiée |
POST | /_emdash/api/admin/transfer/imports/{id}/advance | advanceTransferImport | Faire avancer une importation en cours |
GET | /_emdash/api/admin/transfer/imports/{id}/receipt | getTransferImportReceipt | Obtenir un reçu d’importation |
GET | /_emdash/api/admin/transfer/exports | listTransferExports | Lister les exportations de site |
POST | /_emdash/api/admin/transfer/exports | createTransferExport | Démarrer une exportation de site |
GET | /_emdash/api/admin/transfer/exports/{id} | getTransferExport | Obtenir une exportation de site |
POST | /_emdash/api/admin/transfer/exports/{id}/advance | advanceTransferExport | Faire avancer une exportation de site |
GET | /_emdash/api/admin/transfer/exports/{id}/manifest | getTransferExportManifest | Télécharger un manifeste d’exportation |
GET | /_emdash/api/admin/transfer/exports/{id}/files/{path} | downloadTransferExportFile | Télécharger un fichier d’exportation |
GET | /_emdash/api/admin/transfer/exports/{id}/archive | downloadTransferExportArchive | Télécharger une archive d’exportation |
GET | /_emdash/api/admin/transfer/approvals | listTransferApprovals | Lister les approbations de transfert |
POST | /_emdash/api/admin/transfer/approvals/{id}/approve | approveTransferApproval | Approuver une demande de transfert |
POST | /_emdash/api/admin/transfer/approvals/{id}/deny | denyTransferApproval | Refuser une demande de transfert |
Cycle de vie du contenu et bylines
La référence du cycle de vie du contenu définit l’état, la révision, les permissions, les conflits et le comportement des hooks partagés par REST, MCP, la CLI et le panneau d’administration.
Les lectures de contenu renvoient un jeton opaque _rev lorsqu’il est disponible. Envoyez _rev avec PUT /content/{collection}/{id} pour éviter d’écraser une modification faite depuis la lecture. Un jeton obsolète produit un conflit ; relisez l’élément avant de réessayer. La CLI rend cette vérification obligatoire pour content update, tandis que le champ REST reste optionnel pour les clients qui choisissent délibérément une écriture inconditionnelle.
Lire et mettre à jour une entrée
Lisez l’entrée avant de la modifier :
GET /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN
La réponse contient ses champs, l’état de publication et le jeton de révision :
{
"success": true,
"data": {
"item": {
"id": "01JARTICLE0000000000000000",
"type": "articles",
"slug": "launch-notes",
"status": "published",
"data": { "title": "Launch notes" }
},
"_rev": "opaque-revision-token"
}
}
Envoyez uniquement les champs à modifier, avec le jeton de cette lecture :
PUT /_emdash/api/content/articles/01JARTICLE0000000000000000
Authorization: Bearer $EMDASH_TOKEN
Content-Type: application/json
{
"data": { "title": "Updated launch notes" },
"_rev": "opaque-revision-token"
}
Modifier une entrée publiée crée un brouillon tandis que la version précédente reste en ligne. Appelez l’opération de comparaison pour examiner les deux versions, puis publiez le brouillon ou abandonnez-le. Dépublier conserve le contenu et sa date de publication, annule toute planification en attente et retire l’entrée du site en ligne.
Les corps de création et de mise à jour acceptent des crédits byline, et les réponses de contenu incluent la byline principale et les crédits ordonnés. La liste de contenu peut filtrer par identifiants byline stockés et inclure optionnellement la byline inférée d’un auteur. La création et la gestion des enregistrements byline eux-mêmes passent par les outils MCP byline, pas le contrat REST public.
Les opérations du cycle de vie distinguent la suppression logique de la suppression définitive. Restaurer remet le contenu de la corbeille en brouillon sans planification ; la suppression définitive retire un élément de la corbeille et ne peut pas être annulée. Publier, dépublier, planifier, annuler la planification, comparer, abandonner le brouillon et dupliquer sont des opérations distinctes pour que les clients demandent une transition d’état à la fois.
Verrou d’édition d’entrée
Les collections peuvent prendre un verrou d’édition de sept minutes lorsqu’un éditeur ouvre une entrée. Utilisez les trois opérations sur /content/{collection}/{id}/lock pour lire, acquérir ou renouveler et libérer le bail.
Une réponse de lecture ou d’acquisition indique si le verrouillage est activé, si l’appelant détient le bail et qui le détient actuellement :
{
"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"
}
}
}
Lorsqu’une collection a le verrouillage d’édition désactivé, enabled est false et aucun bail n’est pris. Acquérir à nouveau le même verrou et enregistrer l’entrée prolongent tous deux un bail détenu par l’appelant.
Le corps d’acquisition peut inclure un token opaque identifiant une session d’édition et takeover: true lorsque l’utilisateur choisit de remplacer le bail d’un autre éditeur. Passez le même token en paramètre de requête lors de la libération du verrou. Un second onglet du même compte ne pourra alors pas libérer par erreur le bail du premier.
Lorsqu’un autre utilisateur détient le bail, les écritures de contenu protégées renvoient 409 ENTRY_LOCKED. Les détails d’erreur identifient le détenteur et l’expiration. Pour outrepasser le verrou, envoyez "overrideLock": true dans le corps JSON d’une écriture avec corps, ou ?overrideLock=true pour une opération DELETE sans corps.
Sélections de référence
Un champ reference lie une entrée à des entrées d’une autre collection via une relation. Sa valeur ne fait pas partie de data et est indexée par groupe de traduction, de sorte que chaque traduction d’une entrée partage une sélection.
Les corps de création et de mise à jour portent les sélections sous references, indexées par slug de champ, chacune un tableau d’au plus 1000 identifiants d’entrée dans l’ordre d’affichage. EmDash écrit la sélection dans la même transaction que l’entrée. La mise à jour suivante remplace l’auteur de l’entrée :
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"
}
Un champ lié à l’extrémité enfant de sa relation sélectionne les entrées pointant vers celle en cours d’écriture, sans ordre propre. Les limites de relation s’appliquent aux deux extrémités ; une sélection qui donnerait à une entrée liée plus de parents que la relation ne le permet est rejetée, tout comme une qui lie trop d’entrées.
Sur une collection qui conserve les révisions, une sélection modifiée sur une entrée publiée est mise en attente dans le brouillon avec les autres modifications en attente de l’entrée. Elle devient en ligne à la publication et est abandonnée avec le brouillon. La publication revérifie l’ensemble de la sélection par rapport aux limites de la relation.
Une lecture d’un seul élément renvoie references indexées par slug de champ. Chaque champ contient la première page des entrées liées, 50, avec nextCursor lorsqu’il y en a plus, et indique l’identifiant, le slug, la collection, le titre affiché, la locale résolue et le groupe de traduction de chaque entrée. Un appelant autorisé à lire les brouillons voit une sélection en attente lorsque le brouillon en porte une. L’opération de liste de contenu n’inclut pas les références.
Les définitions de relation et le parcours des liens sont des routes admin, absentes d’OpenAPI et hors du contrat public. Écrivez et lisez les sélections via les opérations de contenu ci-dessus et affichez-les sur un site avec getEmDashEntry() et getEmDashReferences().
Traductions
Le contrat REST public expose les traductions de contenu et les traductions de définitions de taxonomie. La création de contenu accepte translationOf, et la création de taxonomie utilise le même champ pour ajouter une variante de locale. Les opérations de termes de contenu renvoient des assignations sensibles à la locale.
GET /taxonomies/{name} renvoie la définition de la locale par défaut du site lorsque locale est omis, en revenant au code de locale le plus bas uniquement lorsque la locale par défaut n’a pas de définition. Une mise à jour se comporte différemment : lorsque locale est omis, elle modifie la définition au code de locale le plus bas. Passez locale pour qu’une mise à jour de taxonomie traduite atteigne la définition voulue. Si cette locale n’a pas de définition, la mise à jour renvoie NOT_FOUND au lieu de basculer vers une autre locale. L’opération de traductions renvoie chaque définition du groupe partagé et les identifiants acceptés par translationOf.
label et labelSingular appartiennent à la définition d’une locale. hierarchical et collections appartiennent à la taxonomie : chaque locale renvoie les mêmes valeurs, et une mise à jour qui envoie l’un ou l’autre le modifie pour toutes les locales. Créer une définition pour un nom qui existe déjà dans une autre locale l’ajoute à cette taxonomie, que la requête envoie translationOf ou non. La nouvelle définition reprend hierarchical et collections de la taxonomie, et une création avec des valeurs différentes renvoie VALIDATION_ERROR.
Supprimer une taxonomie retire chaque locale de sa définition, tous ses termes et toutes les assignations de ces termes au contenu. Elle ne supprime pas les entrées de contenu elles-mêmes.
L’opération de réordonnancement des termes modifie un groupe de frères. Le tableau ids peut ne contenir qu’une partie de ce groupe ; les termes listés échangent leurs positions existantes et les omis restent en place. Par exemple, réordonner [A, B, C] avec ids: ["C", "A"] produit [C, B, A]. Le réordonnancement ne change pas les relations parent, et un ordre de terme s’applique à chaque locale de son groupe de traduction.
Les routes de traduction de menus, de termes de taxonomie et de bylines ne figurent pas dans le contrat REST public. Leurs listes de traduction prises en charge sont disponibles via menu_translations, taxonomy_term_translations et byline_translations sur le serveur MCP.
Points de terminaison médias
Les opérations médias couvrent le listage, le téléversement, la mise à jour des métadonnées, le remplacement d’images, les dossiers, les informations d’utilisation et la maintenance de l’index d’utilisation. Le guide de la bibliothèque média explique le flux orienté utilisateur et la signification de la couverture d’utilisation.
Lister et inspecter les médias
GET /media prend en charge la pagination par curseur ou par pages numérotées, les filtres par type MIME et nom de fichier, les dossiers et des résumés d’utilisation optionnels. Omettez folderId pour inclure tous les dossiers, ou passez folderId=unfiled pour ne renvoyer que la bibliothèque principale. Définissez includeUsage=1 sur un listage ou une lecture d’élément pour inclure les informations d’utilisation ; toute autre valeur est invalide.
usage.count compte les lignes de contenu actives distinctes ou locales dont la source indexée actuelle référence l’élément média, plus chaque paramètre de site qui le sélectionne (logo, favicon, seo.defaultOgImage). Les références répétées dans une entrée comptent une fois, et les entrées en corbeille ne comptent pas. Le nombre n’est visible que pour les appelants autorisés à lire les brouillons ; les autres lecteurs média autorisés reçoivent count: null car le décompte pourrait révéler du contenu brouillon.
GET /media/{id}/usage renvoie les entrées de contenu référençant le média, paginées. Chaque page inclut aussi siteSettings, les paramètres de site sélectionnant l’élément média, par exemple [{ "setting": "favicon" }]. Les paramètres de site sont lus depuis les valeurs stockées à chaque requête et ne dépendent pas de l’indexation d’utilisation.
Chaque résultat d’utilisation inclut un statut de couverture :
| Statut | Signification |
|---|---|
complete | Chaque collection enregistrée a une couverture d’utilisation à jour. |
never | Aucune collection enregistrée n’a terminé une réparation initiale d’utilisation. |
running | Une réparation est en cours. |
partial | Seule une partie de l’ensemble de collections enregistrées a une couverture à jour. |
failed | La couverture a échoué sur l’ensemble de collections enregistrées. |
stale | L’index est plus ancien que le contenu qu’il décrit. |
unknown | L’état stocké n’est pas reconnu par cette version d’EmDash. |
Seul complete permet de traiter un décompte nul comme complet dans les types de champs indexés. Les décomptes sont indicatifs pendant les écritures concurrentes ; ils ne verrouillent pas l’élément média ni ne garantissent qu’une suppression est sûre. L’indexation d’utilisation couvre les champs image et fichier, les champs répéteur d’image, les blocs image et galerie Portable Text, et les médias déclarés par des versions de bloc conservées dans les collections EmDash. Le logo du site, le favicon et l’image sociale par défaut sont aussi signalés. L’utilisation n’inclut pas les blocs Portable Text personnalisés, le code applicatif, le HTML rendu, d’autres paramètres, les menus, les widgets, les données de plugins, les sites externes ni les actifs réservés au fournisseur.
Téléversement multipart direct
Envoyez un fichier via EmDash en le publiant comme champ file d’une requête multipart :
curl --request POST \
--header "Authorization: Bearer $EMDASH_TOKEN" \
--form "file=@./cover.jpg;type=image/jpeg" \
https://example.com/_emdash/api/media
curl ajoute la limite multipart. Ne définissez pas manuellement l’en-tête Content-Type. Le schéma OpenAPI MediaDirectUploadBody liste les champs de métadonnées optionnels et les schémas de réponse distinguent un nouveau téléversement d’un élément existant dédupliqué.
Le corps multipart peut aussi inclure width et height d’image, un fieldId dont la liste de types MIME autorisés doit s’appliquer, et une thumbnail réduite pour créer un placeholder basse qualité. Un nouveau fichier renvoie 201 Created et est prêt immédiatement. Des octets identiques renvoient l’élément média existant avec 200 OK et deduplicated: true.
Flux de cible de téléversement
Utilisez le flux de cible de téléversement lorsque le client peut téléverser directement vers un stockage compatible S3. L’élément média reste en attente et n’apparaît pas dans la bibliothèque standard tant que la confirmation n’a pas réussi.
-
Demander une cible de téléversement
POST /_emdash/api/media/upload-url Authorization: Bearer $EMDASH_TOKEN Content-Type: application/json { "filename": "cover.jpg", "contentType": "image/jpeg", "size": 102400 }La réponse fournit
uploadUrl,method,headers,mediaId,storageKeyet une expiration. LorsquecontentHashcorrespond à un fichier existant de même type MIME et taille, la réponse définitexisting: true; utilisez cet élément média et ne téléversez ni ne confirmez une autre copie. -
Téléverser les octets
Utilisez la méthode et les en-têtes renvoyés. Résolvez une URL relative à la racine par rapport au site EmDash et incluez le jeton Bearer. Envoyez uniquement les en-têtes de téléversement renvoyés vers une URL absolue sur une autre origine.
-
Confirmer le téléversement
POST /_emdash/api/media/01JMEDIA000000000000000000/confirm Authorization: Bearer $EMDASH_TOKEN Content-Type: application/json { "size": 102400, "width": 1920, "height": 1080 }La confirmation vérifie l’objet stocké et passe l’élément de
pendingàready. La taille et les dimensions fournies doivent correspondre au fichier téléversé.
Le stockage local et R2 natif renvoient une cible de téléversement EmDash same-origin. Le stockage compatible S3 peut renvoyer une URL externe signée. Les éléments en attente restent hors de la liste média standard tant que la confirmation n’a pas réussi.
Erreurs de téléversement
Les erreurs suivantes exigent une action de récupération différente :
| Statut | Code | Action |
|---|---|---|
400 | NO_FILE | Ajoutez le champ file à une requête multipart ou envoyez le corps de téléversement manquant. |
400 | INVALID_TYPE | Utilisez un type MIME autorisé correspondant à l’élément média en attente. |
400 | VALIDATION_ERROR | Corrigez les métadonnées manquantes ou invalides, y compris les valeurs au-delà de la limite de taille configurée. |
400 | FILE_NOT_FOUND | Téléversez l’objet vers la cible renvoyée avant de confirmer. |
400 | UPLOAD_SIZE_MISMATCH | Redémarrez le flux avec la bonne taille ; les tailles déclarée, téléversée et confirmée doivent concorder. |
400 or 409 | INVALID_STATE | Lisez l’élément média avant de réessayer. Il peut ne plus être en attente, ou une autre requête l’a peut-être modifié pendant la confirmation. |
404 | NOT_FOUND | Utilisez un identifiant média en attente existant. |
413 | PAYLOAD_TOO_LARGE | Réduisez la taille du fichier ou augmentez maxUploadSize avant de lancer un autre téléversement. |
Dossiers médias
Les noms de dossier sont rognés, limités à 200 caractères et comparés après normalisation Unicode et mise en minuscules. Des noms comme Photos, photos et PHOTOS entrent donc en conflit. Supprimer un dossier renvoie ses médias à la bibliothèque principale ; cela ne supprime pas les médias, ne change pas les identifiants ou URL média ni les enregistrements d’utilisation.
Réparer l’utilisation média
L’activation, la progression, les files de travail, le nettoyage des suppressions et la réparation de l’utilisation média sont des opérations opérateur sous /_emdash/api/admin/media-usage/. Les utilisateurs par session ont besoin de schema:manage ; les jetons Bearer ont aussi besoin du scope admin.
Si le suivi est désactivé, mettez en pause les écrivains directs de base de données avant l’activation. EmDash bloque temporairement les écritures de contenu et de schéma envoyées via ses API pendant la configuration, mais ne peut pas arrêter un autre processus écrivant directement dans la base de données.
- Arrêtez les écrivains directs de base de données et attendez la fin des écritures en cours.
- Lisez l’état d’activation.
expandedsignifie suivi désactivé,activatingsignifie qu’EmDash prépare les collections, etactivesignifie que les nouveaux changements de référence média sont suivis. - Envoyez une requête d’activation avec
{ "writersDrained": true }. - Envoyez les requêtes de progression une par une, en attendant chaque
nextRequestInMsrenvoyé, jusqu’à ce que l’activation soitactive. - Reprenez les écritures directes en base de données.
- Poursuivez les requêtes de progression jusqu’à ce que l’indexation historique soit
readyetnextRequestInMssoitnull.
Si une requête d’écriture expire ou renvoie 409 ou 500, lisez l’état d’activation et de progression avant de réessayer. Les lots terminés restent enregistrés. Lorsque lastErrorCode est défini, gardez les écrivains directs arrêtés, résolvez le problème signalé et envoyez une nouvelle tentative confirmée. L’activation ne peut pas être annulée ni réinitialisée après le démarrage ; testez cette procédure sur une copie de staging et conservez une sauvegarde de base de données à jour.
Les opérations de liste de travail exposent l’indexation d’entrées échouée ou retardée sans renvoyer le contenu, les références média, les jetons de bail, les erreurs brutes de base de données ni un décompte exact de backlog. Réessayer un élément est idempotent. 409 WORK_LEASE_ACTIVE signifie qu’un worker traite encore l’élément ; la réponse inclut details.leaseExpiresAt, attendez jusqu’à ce moment et relisez l’élément avant de réessayer. 409 WORK_CHANGED signifie qu’une autre requête a modifié l’élément de travail ; lisez son état actuel plutôt que d’écraser le travail plus récent.
L’opération de réparation accepte { "scope": "collection", "collection": "articles" } ou { "scope": "all" }. Une réparation de toutes les collections s’exécute de façon synchrone et séquentielle, ce qui peut prendre longtemps sur un grand site. Une réponse 200 peut quand même signaler partial, failed ou stale ; inspectez data.status, le statut par collection et les décomptes sources avant de considérer la réparation terminée.
Transfert de site
Les opérations de transfert sous /_emdash/api/admin/transfer/ exportent un site sous forme de paquet de site et en importent un dans un site vide. Le guide de transfert de site décrit le flux d’exportation, de téléversement, d’analyse, d’exécution et de reçu.
Les utilisateurs par session ont besoin de la permission transfer:export ou transfer:import, réservée aux administrateurs. Les jetons Bearer ont besoin de admin ou du scope transfer:export, transfer:analyze ou transfer:execute nommé par chaque opération. Les opérations d’approbation n’acceptent que les sessions connectées. Elles tranchent les demandes faites par les outils MCP site_export_start et site_import_start ; les opérations REST d’exportation et d’exécution ne prennent pas d’approbation.
Pendant qu’une importation s’exécute, et après échec ou annulation jusqu’à abandon, la plupart des autres opérations d’écriture renvoient 503 TRANSFER_IMPORT_IN_PROGRESS. Le guide liste les opérations qui restent disponibles.
Pagination
Les opérations de liste décrivent leurs paramètres de pagination dans OpenAPI. La plupart des opérations paginées par curseur acceptent un cursor opaque et une limit de 1 à 100, par défaut 50. Renvoyez le nextCursor de la réponse précédente tel quel ; ne l’inspectez ni ne le construisez. Certaines opérations médias prennent aussi en charge les pages numérotées, et certaines listes spécialisées utilisent des limites différentes ; les clients générés doivent suivre le schéma de chaque opération.
Tokeniseurs de recherche
L’opération d’activation de recherche stocke un tokeniseur par collection. Le modifier sur une collection avec recherche activée reconstruit l’index de cette collection.
| Valeur | Usage |
|---|---|
porter unicode61 | Par défaut pour le contenu anglais bénéficiant du stemming Porter. |
unicode61 | Langues utilisant des séparateurs de mots sans stemming anglais. |
trigram | Texte sans espaces, y compris japonais, chinois, thaï, khmer, lao et birman, ou collections nécessitant une correspondance par sous-chaîne. Les requêtes de moins de trois caractères Unicode ne renvoient aucune correspondance. |
Désactiver la recherche conserve le tokeniseur stocké pour la prochaine activation. L’opération de reconstruction utilise le tokeniseur stocké et les poids de champ de la collection.
Commentaires et redirections
Les soumissions publiques de commentaires entrent dans la file de modération. Les opérations admin de commentaires listent tous les statuts, renvoient des comptages, mettent à jour un statut, modèrent en lot et suppriment définitivement un commentaire. Une réponse 429 signifie que la limite de débit de soumission a été atteinte.
Les opérations de redirection gèrent séparément les règles de redirection et le journal 404 enregistré. L’élagage retire les entrées sélectionnées par le corps de la requête, tandis que DELETE /redirects/404s efface tout le journal. Aucune de ces opérations ne supprime les règles de redirection.