Riferimento API REST

In questa pagina

EmDash espone la sua interfaccia di programmazione applicativa (API) supportata sotto /_emdash/api/. Usate il documento OpenAPI 3.1 generato per parametri di richiesta, body, schemi di risposta, codici di stato e generazione dei client:

GET /_emdash/api/openapi.json

Il documento è generato dagli stessi schemi Zod usati dall’API. Riflette anche la dimensione massima configurata per il caricamento dei media.

Limite del contratto pubblico

Il documento OpenAPI delimita l’API REST supportata. EmDash ha anche route per l’interfaccia admin e i flussi di protocollo. Una route presente nel codice sorgente ma assente da OpenAPI non è un’operazione REST supportata per i client esterni.

Questa distinzione vale per backup, amministrazione delle byline, attraversamento delle relazioni, gestione plugin, setup, import e route di autenticazione. Usate la guida ai backup per i backup e gli strumenti byline MCP per la gestione byline supportata. Gli endpoint OAuth sono endpoint di protocollo; scopriteli dai metadati descritti nella sezione MCP OAuth invece di trattarli come endpoint REST applicativi.

Autenticazione e autorizzazione

La maggior parte delle operazioni accetta un cookie di sessione EmDash o un token Bearer. Inviate un personal access token o un OAuth access token nell’header Authorization:

Authorization: Bearer $EMDASH_TOKEN

I token Bearer sono limitati dagli scope e dal ruolo dell’utente associato. Le richieste con sessione usano il ruolo dell’utente. Vedete ruoli utente e scope dei token per il modello di autorizzazione.

GET e POST /_emdash/api/comments/{collection}/{contentId} sono pubblici. L’operazione GET restituisce i commenti approvati; l’operazione POST invia un commento in moderazione. Le restanti operazioni di moderazione commenti richiedono autenticazione.

Protezione da cross-site request forgery

Per una richiesta che modifica lo stato autenticata con un cookie di sessione, includete questo header:

X-EmDash-Request: 1

Le richieste con token Bearer non richiedono l’header perché non usano credenziali implicite del browser. Le richieste del browser a un’operazione di scrittura pubblica devono inviare l’header oppure avere un Origin che corrisponda all’origine pubblica o di richiesta del sito EmDash.

Involucri di risposta

Una risposta JSON riuscita imposta success su true e colloca il risultato specifico dell’operazione in data:

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

In caso di errore, success è false e sono inclusi un codice stabile leggibile dalla macchina e un messaggio. Alcuni errori includono anche details strutturati:

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

Usate i codici di stato e gli schemi di errore di ogni operazione OpenAPI. Gli stati comuni sono 400 per input non valido, 401 per credenziali mancanti o non valide, 403 per scope o permesso insufficiente, 404 per risorsa assente, 409 per conflitto di stato, 413 per upload troppo grande, 422 quando un plugin rifiuta il salvataggio e 500 per errore interno.

Inventario degli endpoint

L’ID operazione è stabile nel contratto generato ed è spesso usato come nome del metodo dai generatori di client OpenAPI. L’inventario seguente è verificato rispetto al documento OpenAPI generato.

Contenuti

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

Media

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

Schema

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

Commenti

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

Tassonomie

MetodoPercorsoOperazioneRiepilogo
GET/_emdash/api/taxonomieslistTaxonomiesList all taxonomy definitions
GET/_emdash/api/taxonomies/{name}getTaxonomyGet a taxonomy definition
PUT/_emdash/api/taxonomies/{name}updateTaxonomyUpdate a taxonomy definition
DELETE/_emdash/api/taxonomies/{name}deleteTaxonomyDelete a taxonomy, its terms, and their content assignments
GET/_emdash/api/taxonomies/{name}/translationslistTaxonomyTranslationsList every locale variant of a taxonomy definition
POST/_emdash/api/taxonomies/{name}/reorderreorderTermsSet the manual order of one sibling group of terms
GET/_emdash/api/taxonomies/{name}/termslistTermsList terms for a taxonomy
POST/_emdash/api/taxonomies/{name}/termscreateTermCreate a term
GET/_emdash/api/taxonomies/{name}/terms/{slug}getTermGet a term by slug
PUT/_emdash/api/taxonomies/{name}/terms/{slug}updateTermUpdate a term
DELETE/_emdash/api/taxonomies/{name}/terms/{slug}deleteTermDelete a term
MetodoPercorsoOperazioneRiepilogo
GET/_emdash/api/menuslistMenusList all menus with item counts
POST/_emdash/api/menuscreateMenuCreate a menu
GET/_emdash/api/menus/{name}getMenuGet a menu with all items
PUT/_emdash/api/menus/{name}updateMenuUpdate a menu
DELETE/_emdash/api/menus/{name}deleteMenuDelete a menu and its items
POST/_emdash/api/menus/{name}/itemscreateMenuItemAdd an item to a menu
PUT/_emdash/api/menus/{name}/items/{id}updateMenuItemUpdate a menu item
DELETE/_emdash/api/menus/{name}/items/{id}deleteMenuItemDelete a menu item
POST/_emdash/api/menus/{name}/reorderreorderMenuItemsBatch reorder menu items

Sezioni

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

Widgets

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

Impostazioni

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

Ricerca

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

Reindirizzamenti

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

Utenti

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

Trasferimento

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

Ciclo di vita dei contenuti e byline

Il riferimento al ciclo di vita dei contenuti definisce stato, revisione, permessi, conflitti e comportamento degli hook condivisi da REST, MCP, CLI e pannello admin.

Le letture di contenuto restituiscono un token _rev opaco quando disponibile. Inviate _rev con PUT /content/{collection}/{id} per evitare di sovrascrivere una modifica avvenuta dopo la lettura. Un token obsoleto produce un conflitto; rileggete la voce prima di riprovare. La CLI rende obbligatorio questo controllo per content update, mentre il campo REST resta opzionale per i client che scelgono deliberatamente una scrittura incondizionata.

Leggere e aggiornare una voce

Leggete la voce prima di modificarla:

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

La risposta contiene i campi, lo stato di pubblicazione e il token di revisione:

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

Inviate solo i campi da modificare, insieme al token ottenuto con quella lettura:

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

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

Modificare una voce pubblicata crea una bozza mentre la versione precedente resta online. Usate l’operazione di confronto per rivedere entrambe le versioni, poi pubblicate la bozza o scartatela. Annullare la pubblicazione mantiene contenuto e data di pubblicazione, cancella eventuali pianificazioni in sospeso e rimuove la voce dal sito live.

I body di creazione e aggiornamento accettano crediti byline; le risposte di contenuto includono la byline principale e i crediti ordinati. L’elenco contenuti può filtrare per ID byline memorizzati e includere opzionalmente la byline dedotta di un autore. Creare e gestire i record byline avviene tramite gli strumenti byline MCP, non il contratto REST pubblico.

Le operazioni del ciclo di vita distinguono l’eliminazione soft da quella permanente. Il ripristino restituisce contenuti nel cestino come bozza senza pianificazione; l’eliminazione permanente rimuove una voce nel cestino e non è reversibile. Pubblicare, annullare pubblicazione, pianificare, annullare pianificazione, confrontare, scartare bozza e duplicare sono operazioni separate così i client possono richiedere una transizione di stato alla volta.

Blocco modifica voce

Le collection possono acquisire un blocco di modifica di sette minuti quando un editor apre una voce. Usate le tre operazioni su /content/{collection}/{id}/lock per leggere, acquisire o rinnovare e rilasciare il lease.

Una risposta di lettura o acquisizione indica se il blocco è attivo, se il chiamante detiene il lease e chi lo detiene attualmente:

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

Se una collection ha il blocco modifica disabilitato, enabled è false e nessun lease viene acquisito. Ri-acquisire lo stesso blocco e salvare la voce estendono entrambi un lease detenuto dal chiamante.

Il body di acquisizione può includere un token opaco che identifica una sessione di modifica e takeover: true quando l’utente sceglie di sostituire il lease di un altro editor. Passate lo stesso token come parametro di query al rilascio del blocco. Una seconda scheda dello stesso account non può rilasciare per errore il lease della prima.

Quando un altro utente detiene il lease, le scritture protette su contenuto restituiscono 409 ENTRY_LOCKED. I dettagli dell’errore identificano il detentore e la scadenza. Per ignorare il blocco, inviate "overrideLock": true nel body JSON di una scrittura con body, oppure ?overrideLock=true per un’operazione DELETE senza body.

Selezioni di riferimento

Un campo reference collega una voce a voci in un’altra collection tramite una relazione. Il suo valore non fa parte di data ed è indicizzato per gruppo di traduzione, quindi ogni traduzione di una voce condivide una selezione.

I body di creazione e aggiornamento portano le selezioni sotto references, indicizzate per slug del campo, ciascuna un array di al massimo 1000 ID voce in ordine di visualizzazione. EmDash scrive la selezione nella stessa transazione della voce. L’aggiornamento seguente sostituisce l’autore della voce:

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 campo legato all’estremità figlio della relazione seleziona le voci che puntano a quella scritta, senza ordine proprio. I limiti della relazione valgono su entrambe le estremità; una selezione che darebbe a una voce collegata più genitori di quanto la relazione consenta viene rifiutata come una che collega troppe voci.

Su una collection con revisioni, una selezione modificata su una voce pubblicata resta in bozza con le altre modifiche in sospeso. Diventa live alla pubblicazione e viene scartata con la bozza. La pubblicazione ricontrolla l’intera selezione rispetto ai limiti della relazione.

Una lettura singola restituisce references indicizzate per slug del campo. Ogni campo contiene la prima pagina delle voci collegate, 50 elementi, con nextCursor se ce ne sono altre, e riporta ID, slug, collection, titolo visualizzato, locale risolto e gruppo di traduzione di ogni voce. Un chiamante autorizzato a leggere bozze vede una selezione in staging se la bozza ne ha una. L’operazione di elenco contenuti non include i riferimenti.

Definizioni di relazione e attraversamento link sono route admin, assenti da OpenAPI e fuori dal contratto pubblico. Scrivete e leggete le selezioni tramite le operazioni contenuto sopra e renderizzatele sul sito con getEmDashEntry() e getEmDashReferences().

Traduzioni

Il contratto REST pubblico espone traduzioni di contenuto e definizioni di tassonomia. La creazione contenuto accetta translationOf; la creazione tassonomia usa lo stesso campo per aggiungere una variante di locale. Le operazioni content-term restituiscono assegnazioni sensibili al locale.

GET /taxonomies/{name} restituisce la definizione del locale predefinito del sito se locale è omesso, ricadendo sul codice locale più basso solo se il predefinito non ha definizione. Un aggiornamento si comporta diversamente: senza locale modifica la definizione con il codice locale più basso. Passate locale così un aggiornamento di tassonomia tradotta raggiunge la definizione prevista. Se quel locale non ha definizione, l’aggiornamento restituisce NOT_FOUND invece di ricadere su un altro locale. L’operazione translations restituisce ogni definizione nel gruppo condiviso e gli ID accettati da translationOf.

label e labelSingular appartengono alla definizione di un locale. hierarchical e collections appartengono alla tassonomia: ogni locale restituisce gli stessi valori e un aggiornamento che invia uno dei due li modifica per tutti i locale. Creare una definizione per un nome già presente in un altro locale la aggiunge a quella tassonomia, indipendentemente da translationOf nella richiesta. La nuova definizione eredita hierarchical e collections della tassonomia; una create con valori diversi restituisce VALIDATION_ERROR.

Eliminare una tassonomia rimuove ogni locale della definizione, tutti i termini e tutte le assegnazioni di quei termini al contenuto. Non elimina le voci di contenuto.

L’operazione di riordino termini modifica un gruppo di fratelli. L’array ids può contenere solo parte del gruppo; i termini elencati scambiano le posizioni esistenti e quelli omessi restano dove sono. Ad esempio, riordinare [A, B, C] con ids: ["C", "A"] produce [C, B, A]. Il riordino non cambia le relazioni genitore; un ordine termini vale per ogni locale nel suo gruppo di traduzione.

Le route di traduzione menu, termini tassonomia e byline non sono nel contratto REST pubblico. Gli elenchi supportati sono disponibili tramite menu_translations, taxonomy_term_translations e byline_translations sul server MCP.

Endpoint media

Le operazioni media coprono elenco, upload, aggiornamento metadati, sostituzione immagine, cartelle, informazioni d’uso e manutenzione dell’indice d’uso. La guida alla libreria media spiega il flusso per l’utente e il significato della copertura d’uso.

Elencare e ispezionare i media

GET /media supporta paginazione a cursore o a pagine numerate, filtri MIME e nome file, cartelle e riepiloghi d’uso opzionali. Omettete folderId per includere ogni cartella, oppure passate folderId=unfiled per solo la libreria principale. Impostate includeUsage=1 su elenco o lettura singola per le informazioni d’uso; qualsiasi altro valore non è valido.

usage.count conta righe contenuto attive distinte o locale il cui sorgente indicizzato corrente referenzia il media, più ogni impostazione sito che lo seleziona (logo, favicon, seo.defaultOgImage). Riferimenti ripetuti in una voce contano una volta; le voci nel cestino no. Il numero è visibile solo a chi può leggere bozze; altri lettori media autorizzati ricevono count: null perché il conteggio potrebbe rivelare contenuto bozza.

GET /media/{id}/usage restituisce a pagine le voci contenuto che referenziano il media. Ogni pagina include anche siteSettings, le impostazioni che selezionano il media, ad esempio [{ "setting": "favicon" }]. Le impostazioni sito sono lette dalle impostazioni memorizzate a ogni richiesta e non dipendono dall’indicizzazione d’uso.

Ogni risultato d’uso include uno stato di copertura:

StatusSignificato
completeOgni collection registrata ha copertura d’uso aggiornata.
neverNessuna collection registrata ha completato una riparazione d’uso iniziale.
runningUna riparazione è in corso.
partialSolo parte delle collection registrate ha copertura aggiornata.
failedLa copertura è fallita sull’insieme di collection registrate.
staleL’indice è più vecchio del contenuto che descrive.
unknownLo stato memorizzato non è riconosciuto da questa versione di EmDash.

Solo con complete si può trattare un conteggio zero come completo nei tipi di campo indicizzati. I conteggi sono indicativi durante scritture concorrenti; non bloccano il media né garantiscono che l’eliminazione sia sicura. L’indicizzazione d’uso copre campi immagine e file, campi immagine repeater, blocchi immagine e galleria Portable Text e media dichiarati da versioni blocco conservate nelle collection EmDash. Sono riportati anche logo sito, favicon e immagine social predefinita. L’uso non include blocchi Portable Text personalizzati, codice applicativo, HTML renderizzato, altre impostazioni, menu, widget, dati plugin, siti esterni o asset solo del provider.

Caricamento multipart diretto

Inviate un file tramite EmDash pubblicandolo come campo file di una richiesta multipart:

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

curl aggiunge il boundary multipart. Non impostate manualmente l’header Content-Type. Lo schema OpenAPI MediaDirectUploadBody elenca i campi metadati opzionali e gli schemi di risposta distinguono un nuovo upload da un elemento esistente deduplicato.

Il body multipart può includere anche width e height dell’immagine, un fieldId la cui allowlist di tipi MIME va applicata e una thumbnail ridimensionata usata per un segnaposto a bassa qualità. Un nuovo file restituisce 201 Created ed è subito pronto. Byte identici restituiscono il media esistente con 200 OK e deduplicated: true.

Flusso di destinazione upload

Usate il flusso di destinazione upload quando il client può caricare direttamente su storage compatibile S3. Il media resta in stato pending e non compare nella libreria standard finché la conferma non riesce.

  1. Richiedere una destinazione di upload

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

    La risposta fornisce uploadUrl, method, headers, mediaId, storageKey e una scadenza. Quando contentHash corrisponde a un file esistente con lo stesso tipo MIME e dimensione, la risposta imposta invece existing: true; usate quel media e non caricare o confermare un’altra copia.

  2. Caricare i byte

    Usate metodo e header restituiti. Risolvete un URL root-relative rispetto al sito EmDash e includete il token Bearer. Inviate solo gli header di upload restituiti a un URL assoluto su un’altra origine.

  3. Confermare l’upload

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

    La conferma verifica l’oggetto memorizzato e cambia lo stato da pending a ready. Dimensione e misure fornite devono corrispondere al file caricato.

Lo storage locale e R2 nativo restituiscono una destinazione upload EmDash same-origin. Lo storage compatibile S3 può restituire un URL esterno firmato. Gli elementi pending restano fuori dall’elenco media standard finché la conferma non riesce.

Errori di upload

I seguenti errori richiedono un’azione di recupero diversa:

StatoCodiceAzione
400NO_FILEAggiungete il campo file a una richiesta multipart oppure inviate il body di upload mancante.
400INVALID_TYPEUsate un tipo MIME consentito che corrisponda al media pending.
400VALIDATION_ERRORCorreggete metadati mancanti o non validi, inclusi valori oltre il limite di dimensione configurato.
400FILE_NOT_FOUNDCaricate l’oggetto sulla destinazione restituita prima di confermarlo.
400UPLOAD_SIZE_MISMATCHRiavviate il flusso con la dimensione corretta; dimensioni dichiarata, caricata e confermata devono coincidere.
400 or 409INVALID_STATELeggete il media prima di riprovare. Potrebbe non essere più pending oppure un’altra richiesta potrebbe averlo modificato durante la conferma.
404NOT_FOUNDUsate un ID media pending esistente.
413PAYLOAD_TOO_LARGERiducete la dimensione del file o aumentate maxUploadSize prima di un altro upload.

Cartelle media

I nomi delle cartelle sono trimmati, limitati a 200 caratteri e confrontati dopo normalizzazione Unicode e minuscolizzazione. Nomi come Photos, photos e PHOTOS quindi entrano in conflitto. Eliminare una cartella restituisce i media alla libreria principale; non elimina media, non cambia ID o URL dei media né i record d’uso.

Riparare l’uso dei media

Attivazione, progresso, code di lavoro, pulizia eliminazioni e riparazione dell’uso media sono operazioni per operatori sotto /_emdash/api/admin/media-usage/. Gli utenti con sessione necessitano schema:manage; i token Bearer richiedono anche lo scope admin.

Se il tracciamento è disattivato, mettete in pausa gli scrittori diretti del database prima dell’attivazione. EmDash blocca temporaneamente le scritture di contenuto e schema inviate tramite le sue API durante il setup, ma non può fermare un altro processo che scrive direttamente nel database.

  1. Fermate gli scrittori diretti del database e attendete il completamento delle scritture in corso.
  2. Leggete lo stato di attivazione. expanded significa tracciamento disattivato, activating che EmDash prepara le collection e active che le nuove modifiche ai riferimenti media sono tracciate.
  3. Inviate una richiesta di attivazione con { "writersDrained": true }.
  4. Inviate richieste di progresso una alla volta, attendendo ogni nextRequestInMs restituito, finché l’attivazione è active.
  5. Riprendete le scritture dirette sul database.
  6. Continuate le richieste di progresso finché l’indicizzazione storica è ready e nextRequestInMs è null.

Se una richiesta di scrittura va in timeout o restituisce 409 o 500, leggete stato di attivazione e progresso prima di riprovare. I batch completati restano registrati. Quando lastErrorCode è impostato, tenete fermi gli scrittori diretti, risolvete il problema segnalato e inviate un retry confermato. L’attivazione non può essere annullata o reimpostata dopo l’avvio: testate la procedura su una copia di staging e mantenete un backup database aggiornato.

Le operazioni di elenco lavori espongono indicizzazioni voce fallite o ritardate senza restituire contenuto, riferimenti media, token di lease, errori DB grezzi o un conteggio esatto del backlog. Riprovare un elemento è idempotente. 409 WORK_LEASE_ACTIVE significa che un worker sta ancora elaborando l’elemento; la risposta include details.leaseExpiresAt: attendete fino a quell’istante e rileggete prima di riprovare. 409 WORK_CHANGED significa che un’altra richiesta ha modificato l’elemento di lavoro; leggete lo stato corrente invece di sovrascrivere il lavoro più recente.

L’operazione di riparazione accetta { "scope": "collection", "collection": "articles" } oppure { "scope": "all" }. Una riparazione su tutte le collection gira in modo sincrono e sequenziale e può richiedere molto tempo su siti grandi. Una risposta 200 può comunque segnalare partial, failed o stale; controllate data.status, lo stato per collection e i conteggi sorgente prima di considerare la riparazione completa.

Trasferimento sito

Le operazioni di trasferimento sotto /_emdash/api/admin/transfer/ esportano un sito come pacchetto sito e ne importano uno in un sito vuoto. La guida al trasferimento sito descrive export, upload, analisi, esecuzione e flusso di ricevuta.

Gli utenti con sessione necessitano del permesso transfer:export o transfer:import, riservato agli amministratori. I token Bearer richiedono admin o lo scope transfer:export, transfer:analyze o transfer:execute indicato da ogni operazione. Le operazioni di approvazione accettano solo sessioni autenticate. Decidono le richieste avviate dagli strumenti MCP site_export_start e site_import_start; le operazioni REST di export ed esecuzione non richiedono approvazione.

Mentre un import è in esecuzione, e dopo un fallimento o annullamento finché non viene abbandonato, la maggior parte delle altre operazioni di scrittura restituisce 503 TRANSFER_IMPORT_IN_PROGRESS. La guida elenca le operazioni che restano disponibili.

Paginazione

Le operazioni di elenco descrivono i parametri di paginazione in OpenAPI. La maggior parte delle operazioni con paginazione a cursore accetta un cursor opaco e un limit da 1 a 100, predefinito 50. Restituite il nextCursor della risposta precedente invariato; non analizzatelo né costruitelo. Alcune operazioni media supportano anche pagine numerate e alcuni elenchi specializzati usano limiti diversi: i client generati dovrebbero seguire lo schema di ogni operazione.

Tokenizer di ricerca

L’operazione di abilitazione ricerca memorizza un tokenizer per ogni collection. Modificarlo su una collection abilitata ricostruisce l’indice di quella collection.

ValoreUso
porter unicode61Predefinito per contenuto inglese che beneficia dello stemming Porter.
unicode61Lingue con separatori di parola che non devono usare lo stemming inglese.
trigramTesto senza spazi, inclusi giapponese, cinese, thailandese, khmer, lao e birmano, o collection che richiedono corrispondenza per sottostringa. Query più corte di tre caratteri Unicode non restituiscono risultati.

Disabilitare la ricerca conserva il tokenizer memorizzato per la prossima abilitazione. L’operazione di rebuild usa il tokenizer memorizzato della collection e i pesi dei campi.

Commenti e reindirizzamenti

Le submission pubbliche di commenti entrano nella coda di moderazione. Le operazioni admin commenti elencano tutti gli stati, restituiscono conteggi, aggiornano uno stato, moderano in blocco ed eliminano definitivamente un commento. Una risposta 429 indica che è stato raggiunto il limite di frequenza di invio.

Le operazioni reindirizzamento gestiscono separatamente regole di reindirizzamento e log 404 registrato. La potatura rimuove le voci selezionate dal body della richiesta, mentre DELETE /redirects/404s svuota l’intero log. Nessuna delle due operazioni elimina le regole di reindirizzamento.