Riferimento API REST

In questa pagina

EmDash espone un’API REST in /_emdash/api/ per la gestione dei contenuti, l’upload di media e le operazioni sugli schemi.

Autenticazione

Le richieste API richiedono l’autenticazione tramite un token Bearer nell’header Authorization:

Authorization: Bearer <token>

Genera token tramite l’interfaccia di amministrazione o in modo programmatico.

Formato di risposta

Tutte le risposte seguono un formato coerente. Una risposta di successo avvolge il risultato in data:

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

Una risposta di errore include un codice, un messaggio e dettagli opzionali:

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

Endpoint dei contenuti

Elencare i contenuti

GET /_emdash/api/content/:collection

Parametri

ParametroTipoDescrizione
collectionstringSlug della collezione (percorso)
cursorstringCursore di paginazione (query)
limitnumberElementi per pagina (query, predefinito: 50)
statusstringFiltrare per stato (query)
orderBystringCampo di ordinamento (query)
orderstringDirezione di ordinamento: asc o desc (query)

Risposta

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

Ottenere un contenuto

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

Risposta

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

Creare un contenuto

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

Corpo della richiesta

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

Risposta

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

Aggiornare un contenuto

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

Corpo della richiesta

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

Eliminare un contenuto

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

Risposta

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

Endpoint dei media

Elencare i media

GET /_emdash/api/media?includeUsage=1

Parametri

ParametroTipoDescrizione
cursorstringCursore di paginazione opaco
limitnumberElementi per pagina, da 1 a 100 (predefinito: 50)
mimeTypestringFiltrare per uno o più tipi MIME separati da virgole
qstringRicerca del nome file senza distinzione maiuscole/minuscole
includeUsage1Includere un riepilogo di usage con copertura su ogni elemento restituito

Risposta

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

Ottenere un media

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

includeUsage è opzionale sia per l’elenco che per l’ottenimento. Il suo unico valore accettato è 1. Quando omesso, la proprietà usage viene omessa e il server non esegue query di utilizzo.

Riepiloghi di utilizzo

usage.count è il numero di righe di contenuto o locali attivi distinti di EmDash la cui sorgente indicizzata corrente selezionata fa riferimento all’elemento media. I riferimenti ripetuti e le varianti di sorgente multiple per la stessa voce di contenuto contano una volta. Il contenuto nel cestino non conta.

Un conteggio numerico può rivelare contenuti simili a bozze. Viene restituito solo quando un utente di sessione ha content:read_drafts, o quando un token API ha lo scope admin e il suo utente associato ha anche quel permesso. Gli altri lettori di media ricevono usage.count: null; questa è una risposta oscurata con successo, non un errore.

Ogni riepilogo richiesto include la copertura aggregata per tutte le collezioni di contenuto attualmente registrate:

StatoSignificato
completeOgni collezione registrata ha una copertura di utilizzo corrente e completata
neverNessuna collezione registrata ha completato una riparazione di utilizzo iniziale
runningUna riparazione di utilizzo è attualmente in corso
partialLa copertura è mista o solo parte dell’ambito registrato è stato indicizzato
failedLa copertura è fallita nell’ambito registrato
staleLa copertura indicizzata è obsoleta
unknownLa copertura memorizzata contiene uno stato che questa versione non riconosce

Solo complete supporta una dichiarazione di zero completo con ambito nei campi gestiti da EmDash descritti di seguito. I conteggi con qualsiasi altro stato sono proiezioni indicizzate e possono sovra-riportare o sotto-riportare. Anche i risultati completi sono consultivi durante le scritture concorrenti; le letture di utilizzo non sono un blocco transazionale e non devono essere usate come garanzia di eliminazione.

Ottenere i dettagli di utilizzo dei media

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

Questo endpoint richiede media:read e content:read_drafts. I chiamanti autenticati con token richiedono anche lo scope admin; lo scope del token non bypassa i permessi dell’utente associato.

limit controlla i gruppi di voci di contenuto per pagina, da 1 a 100 (predefinito: 50). La paginazione non divide mai le sorgenti o le occorrenze per un gruppo di voci restituito.

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

I dettagli autorizzati includono voci attive e eliminate. Un deletedAt non null identifica una voce nel cestino. Le sorgenti sono columns o draft_overlay; le occorrenze identificano il campo supportato e il percorso senza esporre i metadati interni dell’indice.

L’utilizzo dei media copre i riferimenti ai media locali nei campi immagine e file di livello superiore, nei campi immagine dei ripetitori e nei blocchi immagine Portable Text gestiti dalle collezioni di contenuto EmDash. Non scansiona codice personalizzato, HTML renderizzato, impostazioni, menu, widget, dati privati dei plugin, siti esterni o asset esclusivi del provider.

Creare un media

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

Corpo della richiesta

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

Aggiornare un media

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

Corpo della richiesta

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

Eliminare un media

DELETE /_emdash/api/media/:id

Riparare l’utilizzo dei media

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

Ripara l’indice di utilizzo dei media di contenuto per una collezione o per tutte le collezioni di contenuto. Questo è un endpoint amministratore/operatore: i chiamanti autenticati per sessione necessitano di schema:manage, e i token Bearer devono avere lo scope admin perché la rotta è sotto /_emdash/api/admin.

La riparazione di tutto il contenuto viene eseguita in modo sincrono e sequenziale nella versione corrente. Può essere costosa sui siti di grandi dimensioni, quindi i chiamanti dovrebbero attivarla deliberatamente e attendere la risposta.

Corpo della richiesta

Riparare una collezione:

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

Riparare tutte le collezioni di contenuto:

{
	"scope": "all"
}

Il corpo della richiesta è obbligatorio. Slug non validi, chiavi di richiesta sconosciute, scope mancante e richieste senza corpo restituiscono 400 invece di riparare tutto il contenuto per impostazione predefinita.

Risposta

L’endpoint restituisce 200 quando un’invocazione di riparazione produce un risultato strutturato. Ispeziona data.status: failed e stale sono stati del dominio di riparazione, non errori di trasporto.

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

Campi di risposta di livello superiore:

CampoTipoDescrizione
statuscomplete | partial | failed | staleStato di riparazione aggregato
indexedSourceCountnumberSorgenti indicizzate durante la riparazione
failedSourceCountnumberSorgenti fallite durante la riparazione
skippedSourceCountnumberSorgenti saltate, inclusi conflitti obsoleti
deletedSourceCountnumberRighe di utilizzo obsolete eliminate durante la riparazione
collectionsarrayRiepiloghi di riparazione per collezione

Campi di riepilogo per collezione:

CampoTipoDescrizione
collectionstringSlug della collezione
statuscomplete | partial | failed | staleStato di riparazione della collezione
indexedSourceCountnumberSorgenti indicizzate per questa collezione
failedSourceCountnumberSorgenti fallite per questa collezione
skippedSourceCountnumberSorgenti saltate per questa collezione
deletedSourceCountnumberRighe di utilizzo obsolete eliminate per questa collezione
lastErrorCodestring | nullUltimo errore di riparazione della collezione, se disponibile
startedAtstringOra di inizio della riparazione
completedAtstring | nullOra di completamento, o null per risultati obsoleti

Le collezioni sconosciute restituiscono 200 con data.status: "failed" e un lastErrorCode per collezione come COLLECTION_NOT_FOUND. Gli errori di trasporto usano ancora l’involucro di errore standard, inclusi 400, 401, 403, 413 e 500.

Ottenere un file media

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

Serve il contenuto effettivo del file. Solo per l’archiviazione locale.

Endpoint delle revisioni

Elencare le revisioni

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

Parametri

ParametroTipoDescrizione
limitnumberMax revisioni da restituire (predefinito: 50)

Risposta

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

Ottenere una revisione

GET /_emdash/api/revisions/:revisionId

Ripristinare una revisione

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

Ripristina il contenuto allo stato di questa revisione e crea una nuova revisione.

Endpoint dello schema

Elencare le collezioni

GET /_emdash/api/schema/collections

Risposta

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

Ottenere una collezione

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

Parametri

ParametroTipoDescrizione
includeFieldsbooleanIncludere le definizioni dei campi (query)

Creare una collezione

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

Corpo della richiesta

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

Aggiornare una collezione

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

Eliminare una collezione

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

Parametri

ParametroTipoDescrizione
forcebooleanEliminare anche se la collezione ha contenuti (query)

Elencare i campi

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

Creare un campo

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

Corpo della richiesta

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

Aggiornare un campo

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

Eliminare un campo

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

Riordinare i campi

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

Corpo della richiesta

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

Esportazione dello schema

Esportare lo schema (JSON)

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

Esportare lo schema (TypeScript)

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

Restituisce interfacce TypeScript per tutte le collezioni.

Endpoint dei plugin

Elencare i plugin

GET /_emdash/api/admin/plugins

Ottenere un plugin

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

Abilitare un plugin

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

Disabilitare un plugin

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

Codici di errore

CodiceStato HTTPDescrizione
NOT_FOUND404Risorsa non trovata
VALIDATION_ERROR400Dati di input non validi
UNAUTHORIZED401Token mancante o non valido
FORBIDDEN403Permessi insufficienti
CONTENT_LIST_ERROR500Errore nell’elencare i contenuti
CONTENT_CREATE_ERROR500Errore nella creazione del contenuto
CONTENT_UPDATE_ERROR500Errore nell’aggiornamento del contenuto
CONTENT_DELETE_ERROR500Errore nell’eliminazione del contenuto
MEDIA_LIST_ERROR500Errore nell’elencare i media
MEDIA_CREATE_ERROR500Errore nella creazione del media
SCHEMA_CREATE_ERROR500Operazione sullo schema fallita
SLUG_CONFLICT409Lo slug esiste già
RESERVED_SLUG400Lo slug è riservato

Endpoint di ricerca

Ricerca globale

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

Parametri

ParametroTipoDescrizione
qstringQuery di ricerca (obbligatorio)
collectionsstringSlug delle collezioni separati da virgole
statusstringFiltrare per stato (predefinito: published)
limitnumberMax risultati (predefinito: 20)
cursorstringCursore di paginazione

Risposta

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

Suggerimenti di ricerca

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

Restituisce titoli con corrispondenza di prefisso per l’autocompletamento.

Ricostruire l’indice di ricerca

POST /_emdash/api/search/rebuild

Ricostruire l’indice FTS per tutte o specifiche collezioni.

Statistiche di ricerca

GET /_emdash/api/search/stats

Restituisce il conteggio dei documenti indicizzati per collezione.

Endpoint delle sezioni

Elencare le sezioni

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

Ottenere una sezione

GET /_emdash/api/sections/:slug

Creare una sezione

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

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

Aggiornare una sezione

PUT /_emdash/api/sections/:slug

Eliminare una sezione

DELETE /_emdash/api/sections/:slug

Endpoint delle impostazioni

Ottenere tutte le impostazioni

GET /_emdash/api/settings

Aggiornare le impostazioni

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

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

Endpoint dei menu

Elencare i menu

GET /_emdash/api/menus

Ottenere un menu

GET /_emdash/api/menus/:name

Creare un menu

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

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

Aggiornare un menu

PUT /_emdash/api/menus/:name

Eliminare un menu

DELETE /_emdash/api/menus/:name

Aggiungere un elemento al menu

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

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

Riordinare gli elementi del menu

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

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

Endpoint delle tassonomie

Elencare le definizioni delle tassonomie

GET /_emdash/api/taxonomies

Creare una tassonomia

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

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

Elencare i termini

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

Creare un termine

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

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

Aggiornare un termine

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

Eliminare un termine

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

Impostare i termini di una voce

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

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

Endpoint delle aree widget

Elencare le aree widget

GET /_emdash/api/widget-areas

Ottenere un’area widget

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

Creare un’area widget

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

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

Eliminare un’area widget

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

Aggiungere un widget

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

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

Aggiornare un widget

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

Eliminare un widget

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

Riordinare i widget

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

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

Endpoint di gestione utenti

Elencare gli utenti

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

Ottenere un utente

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

Aggiornare un utente

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

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

Abilitare un utente

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

Disabilitare un utente

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

Endpoint di autenticazione

Stato della configurazione

GET /_emdash/api/setup/status

Restituisce se la configurazione è completata e se esistono utenti.

Accesso con Passkey

POST /_emdash/api/auth/passkey/options

Ottenere le opzioni di autenticazione WebAuthn.

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

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

Verificare il passkey e creare una sessione.

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

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

Disconnessione

POST /_emdash/api/auth/logout

Utente corrente

GET /_emdash/api/auth/me

Invitare un utente

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

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

Gestione dei Passkey

GET /_emdash/api/auth/passkey

Elencare i passkey dell’utente.

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

Registrare un nuovo passkey.

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

{
  "name": "MacBook Pro"
}

Rinominare un passkey.

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

Eliminare un passkey.

Endpoint di importazione

Analizzare l’esportazione WordPress

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

file: <WXR file>

Eseguire l’importazione WordPress

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

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

Limitazione del tasso

Gli endpoint API possono essere limitati nel tasso in base alla configurazione del deployment. Quando limitati, le risposte includono:

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

CORS

L’API supporta CORS per le richieste dal browser. Configura le origini consentite nel tuo deployment.