API REST
Routes extraites du routeur réel à chaque build, avec leurs frontières d’authentification.
Sur cette page
Session, origine et CSRF
L’API /api/v1 sert principalement l’administration. Les routes privées exigent une session ou, sur les routes explicitement autorisées, un jeton d’intégration. Le cookie est HttpOnly, SameSite=Lax et Secure lorsque CMS_ORIGIN utilise HTTPS. Les endpoints publics d’extensions sont déclarés séparément et n’exposent pas toutes les fonctions d’administration.
Les mutations par session contrôlent Origin égal à CMS_ORIGIN et x-csrf-token obtenu avec la session. Les requêtes Bearer explicitement autorisées n’utilisent ni cookie ni CSRF. Les corps JSON utilisent Content-Type: application/json ; les uploads média sont binaires. Les mutations publiques d’extensions utilisent leur propre jeton signé.
const sessionResponse = await fetch("/api/v1/session", { credentials: "same-origin" });
if (!sessionResponse.ok) throw new Error("Session required");
const result = await fetch("/api/v1/content", { credentials: "same-origin" });
if (!result.ok) throw new Error("Content request failed");
const contents = await result.json();Contrat et erreurs
GET /api/v1/openapi expose le contrat de l’instance avec tools.read. La référence est extraite des mêmes déclarations. Une permission de route n’énumère pas tous les contrôles métier ; les endpoints d’extensions vérifient leurs permissions déclarées dans le module.
Toutes les routes CMS enregistrées disposent de contrats de paramètres, requêtes, réponses et erreurs. Les réponses HTML, CSS, binaires et les redirections sont distinguées du JSON ; les flux ne sont pas relus pour les valider. Les endpoints concrets des extensions actives sont ajoutés selon les droits de la session et leurs schémas déclarés. Cette documentation ne rend aucune nouvelle route compatible Bearer : seules les 25 routes explicitement autorisées l’acceptent.
| Statut | Interprétation |
|---|---|
| 400 | Entrée invalide. |
| 401 | Session absente ou invalide. |
| 403 | Droits ou origine/CSRF refusés. |
| 409 | Conflit de version, unicité ou référence. |
| 421 | Hôte ou origine de transport refusé par la politique de domaine. |
| 429 | Limitation de tentatives ; respecter Retry-After. |
| 500 | Erreur interne à corréler par requestId. |
| 503 | Service indisponible, maintenance ou transport HTTPS non établi. |
{ "error": { "code": "conflict", "message": "Message de l’opération.", "requestId": "identifiant" } }Les erreurs localisables peuvent ajouter messageKey et params au code et au message de référence. Les clés doivent être connues du catalogue ; les paramètres sont bornés. Un client sans cette clé conserve le message fourni. Les erreurs internes inattendues restent génériques et n’exposent ni SQL, ni pile, ni secret. Certaines protections de domaine interviennent avant le routeur ; vérifiez toujours le statut et le type de réponse.
Filtrer et trier six collections
Les routes administratives content, terms, media, users, audit et jobs acceptent sort et order. sort désigne un seul champ de la liste autorisée ; order vaut asc ou desc. Avec sort seul, le sens est asc. Avec order seul, le sens s’applique au champ historique. Sans ces paramètres, l’ordre antérieur est conservé.
| Route sous /api/v1 | Filtres | Champs sort | Ordre historique |
|---|---|---|---|
| /content | search, type, status, ids, term | title, createdAt, updatedAt, publishedAt | updatedAt desc |
| /terms | search, type, taxonomy, ids | label, slug, taxonomy | label asc |
| /media | search, mimeType | filename, createdAt, size | createdAt desc |
| /users | search, status, roleId | name, email, status, createdAt | createdAt desc |
| /audit | action, actorId | id, action, createdAt | id desc |
| /jobs | status, type | createdAt, runAt, finishedAt, type, status | createdAt desc |
GET /api/v1/content?type=page&status=draft&sort=title&order=asc&page=2
GET /api/v1/media?mimeType=application%2Fpdf&sort=size&order=desc
GET /api/v1/jobs?status=failed&sort=finishedAt&order=descLes filtres se combinent avec un ET logique et s’appliquent avant le décompte et la pagination. search accepte jusqu’à 100 caractères ; la recherche ILIKE porte sur le titre du contenu, le libellé du terme, le nom du fichier média ou le nom et l’e-mail utilisateur. Les motifs % et _ gardent leur sens PostgreSQL. mimeType accepte image/webp ou application/pdf, les formats stockés ; le nouveau titre d’un média n’est pas un champ de recherche ou de tri.
page va de 1 à 100 000, avec 1 par défaut. La réponse conserve items, total, page et pageSize. La taille reste fixe : 25 éléments, ou 50 pour l’audit. La sélection par ids de content et terms conserve une taille de 100. Un paramètre inconnu ou répété, un sort vide ou non autorisé et un sens invalide sont refusés avec HTTP 400. Les noms SQL restent privés et les valeurs sont paramétrées.
L’identifiant unique départage les égalités dans l’ordre croissant, sauf le tri direct de l’audit par id qui suit le sens demandé. Les dates nulles publishedAt et finishedAt restent à la fin dans les deux sens. L’ordre est stable pour un jeu de données inchangé ; OFFSET et les lectures séparées du total et des éléments ne fournissent pas un snapshot entre pages. Des écritures concurrentes peuvent déplacer les résultats.
content et terms exigent content.read, media exige media.read ; leurs accès Bearer existants restent plafonnés aux droits actuels. users, audit et jobs restent réservés aux sessions avec users.manage, audit.read et tools.read. Aucun nouveau contrôle de tri n’est ajouté à l’administration par ce contrat API.
Lire et comparer les révisions
GET /api/v1/content/:id/revisions conserve ses pages de 25 instantanés. L’interface compare une version à celle qui la précède immédiatement, en chargeant au besoin une seule page adjacente. Si une écriture concurrente décale cette paire hors de la page, elle demande d’actualiser plutôt que de comparer deux versions non consécutives. La première révision correspond à la création.
Le helper SDK compareContentRevisions(previous, current) compare les informations, les champs par chemin et les blocs par identifiant stable. La vue signale ajouts, retraits, modifications et déplacements, sans diff mot à mot. Elle limite les champs à 100 différences, les blocs à 50 et leurs paramètres à 100 différences au total ; les extraits de texte sont limités à 300 caractères. Les instantanés conservés ne sont pas réécrits.
La lecture exige content.read et n’enregistre rien. Le rendu échappe les valeurs sans exécuter le HTML ni charger les URL des anciennes versions. La restauration reste une mutation confirmée et versionnée, avec content.update et les contrôles de publication existants ; elle crée un nouveau brouillon. Aucun endpoint de comparaison ni migration n’est ajouté.
API avant PostgreSQL
Quand aucune connexion de base n’est configurée, GET /api/v1/openapi est public et ne décrit que les quatre routes du serveur d’amorçage : bootstrap, install/prerequisites, install/database et openapi. Les contrôles du jeton d’installation, d’origine, de taille et de fréquence restent actifs. Après préparation de la base, le même serveur passe au routeur CMS et l’OpenAPI complet exige tools.read. Une base configurée mais inaccessible ne réactive pas ce serveur d’installation.
Upload et actions média
POST /api/v1/media attend les octets du fichier, x-filename encodé avec encodeURIComponent, Origin et CSRF. Limite : 10 Mo. Le client envoie application/octet-stream, pas multipart/form-data. Les formats acceptés sont JPEG, PNG, WebP, AVIF non animés et PDF ; SVG n’est pas accepté.
MediaEntry expose title, distinct de filename, alt et caption. La migration additive content:2 initialise les médias existants à une chaîne vide, sans modifier leurs versions ou fichiers ; les imports commencent aussi sans titre. Le champ accepte de 0 à 200 unités UTF-16 sans NUL. Les corps HTTP refusent également les substituts Unicode isolés.
PUT /api/v1/media/:id exige media.update et conserve alt et caption requis. title est facultatif pour les anciens clients : son omission conserve la valeur actuelle et une chaîne vide l’efface. Envoyez version pour obtenir le contrôle de concurrence HTTP 409 ; l’interface le fait systématiquement, tandis que l’omission historique de version reste acceptée sans cette garantie. La mutation réussie incrémente la version et journalise media.updated.
Les actions crop et variants sont versionnées. Le recadrage produit un nouveau média avec variantes WebP/AVIF et copie title, alt et caption sans modifier l’original. usage inspecte les dépendances avant remove ; la suppression logique est refusée si le média est référencé. Les PDF sont servis en téléchargement attachment avec nosniff.
Routes enregistrées
169 routes extraites du routeur de cette version. « Session » indique une route authentifiée dont les droits détaillés sont contrôlés dans le service.
/api/v1/integrations/optionsRead available integration scopes and webhook capabilities
/api/v1/integrations/tokensList own API tokens without secret material
/api/v1/integrations/tokensCreate a scoped API token, returned once
/api/v1/integrations/tokens/:id/revokeRevoke an API token owned by the current user
/api/v1/integrations/webhooksList webhook subscriptions without secrets
/api/v1/integrations/webhooksCreate a signed webhook and return its secret once
/api/v1/integrations/webhooks/:idUpdate or disable a versioned webhook; old queued deliveries are cancelled
/api/v1/integrations/webhooks/:id/rotateRotate a webhook signing secret and cancel old queued deliveries
/api/v1/integrations/webhooks/:id/testQueue a signed test event to an enabled webhook
/api/v1/integrations/webhooks/:id/deliveriesRead paginated webhook delivery history
/api/v1/integrations/deliveries/:id/attemptsRead paginated attempt history without remote response bodies
/api/v1/integrations/deliveries/:id/retryRetry a failed delivery whose destination remains unchanged and enabled
/api/v1/install/prerequisitesVerify installation prerequisites with the setup token
/api/v1/install/databaseVerify the configured PostgreSQL connection
/api/v1/install/packsList verified starter packs and their exact contents
/api/v1/installInstall this site and its optional pack once
/api/v1/appearance/drafts/:kind/:nameRead the author's private site draft
/api/v1/appearance/drafts/:kind/:nameAutosave private site work with draft and live version preconditions
/api/v1/appearance/drafts/:kind/:name/discardDiscard a versioned private site draft
/api/v1/appearance/draft-tokens/:kind/:namePrivate stylesheet for a versioned site draft preview
/api/v1/patterns/catalogNamed theme compositions available as copies or synchronized references
/api/v1/themesList installed themes
/api/v1/themesInstall a verified theme package
/api/v1/themes/updatesRead theme update and rollback history
/api/v1/themes/:id/updateBack up and atomically update a theme with compatibility checks
/api/v1/themes/updates/:id/rollbackBack up and restore the code of a previous theme version
/api/v1/themes/:id/activateactivate a theme
/api/v1/themes/:id/removeremove a theme
/api/v1/appearance/documentsList templates, parts and patterns
/api/v1/appearance/documentsSave a versioned site document
/api/v1/appearance/resetReset a site document to its theme default
/api/v1/appearance/settingsRead global styles and theme settings
/api/v1/appearance/settingsSave validated global styles
/api/v1/patternsReusable content block compositions
/api/v1/appearance/revisions/:kind/:nameRead site document revision history
/api/v1/appearance/restoreRestore a site document as a new revision
/api/v1/editor-drafts/:keyRead the current author's private recovery draft
/api/v1/editor-drafts/:keyAutosave private work with draft and content version preconditions
/api/v1/editor-drafts/:key/discardDiscard only the expected version of the current author's recovery draft
/api/v1/taxonomiesList content taxonomies
/api/v1/taxonomiesCreate or update a versioned taxonomy
/api/v1/termsSearch and select taxonomy terms
/api/v1/termsCreate a taxonomy term
/api/v1/terms/:idUpdate a versioned taxonomy term
/api/v1/terms/:id/removeRemove an unused taxonomy term
/api/v1/backups/scheduleConfigure a versioned backup schedule
/api/v1/backups/:id/copy-remotecopy-remote an encrypted backup
/api/v1/backups/:id/import-remoteimport-remote an encrypted backup
/api/v1/jobsRead background jobs with pagination
/api/v1/jobs/:id/historyRead job attempt history
/api/v1/jobs/:id/retryRetry a failed background job
/api/v1/jobs/runRun due registered background jobs
/api/v1/cache/clearClear the server cache
/api/v1/maintenanceRead backup readiness and operation history
/api/v1/backupsList verified encrypted backups
/api/v1/backupsCreate and verify an encrypted backup
/api/v1/backups/:id/exportDownload a verified encrypted backup archive
/api/v1/backups/:id/verifyVerify all encrypted backup files
/api/v1/backups/:id/restore-planPrepare a user-bound expiring restore plan
/api/v1/backups/restoreRestore a reviewed backup after saving the current state
/api/v1/backups/retentionRead local backup retention policy
/api/v1/backups/retentionConfigure local retention after an authenticated complete preview
/api/v1/backups/retention/previewEnqueue a non-destructive bounded retention preview
/api/v1/backups/retention/runEnqueue the currently enabled retention policy
/api/v1/backups/retention/runsRead paginated retention runs
/api/v1/backups/retention/runs/:idRead a retention run and paginated archive decisions
/api/v1/backups/retention/runs/:id/cancelStop retention at the next safe batch boundary
/api/v1/backups/retention/runs/:id/resumeResume an interrupted local retention under an identical enabled policy
/api/v1/login/mfaComplete second-factor verification and create a session
/api/v1/password-reset/requestRequest account recovery without disclosing account existence
/api/v1/password-reset/completeConsume a single-use password-reset token and revoke sessions
/api/v1/account/securityRead own second-factor configuration without secrets
/api/v1/account/mfa/beginbegin own TOTP authentication
/api/v1/account/mfa/confirmconfirm own TOTP authentication
/api/v1/account/mfa/disabledisable own TOTP authentication
/api/v1/account/mfa/regenerateregenerate own TOTP authentication
/api/v1/central/statusRead the optional local account connection status
/api/v1/central/keyInspect the remote signing key before explicitly trusting its fingerprint
/api/v1/central/keyPin a verified registry signing key
/api/v1/central/startstart an optional account connection
/api/v1/central/pollpoll an optional account connection
/api/v1/central/cancelcancel an optional account connection
/api/v1/central/disconnectdisconnect an optional account connection
/api/v1/central/catalogSearch the central catalogue with local installation status
/api/v1/central/entitlementsRead the connected account's acquisitions
/api/v1/central/installAcquire and install a signed catalogue package without activating it
/api/v1/updatesRead core distribution compatibility and update history
/api/v1/updates/importVerify and stage a signed runtime distribution
/api/v1/updates/applyBack up and restart on a compatible signed core release
/api/v1/updates/rollbackRestore the pre-update core and database after explicit confirmation
/api/v1/content-types/:name/validateValidate a versioned schema migration against all existing content
/api/v1/content-types/:nameAtomically migrate a content schema and valid existing values
/api/v1/content-user-optionsSelect active user display names for structured content fields
/api/v1/content/:id/removePermanently delete unreferenced trashed content and its revisions
/api/v1/media-optionsSelect live media with image filtering
/api/v1/media/:id/usageInspect media dependencies including revisions and private drafts
/api/v1/media/:id/cropCreate an immutable cropped image with responsive variants
/api/v1/media/:id/variantsGenerate missing responsive image variants
/api/v1/media/:id/removeTombstone an unused media object before delayed physical purging
/api/v1/extensionsRead permitted declarative extension contributions
/api/v1/extensions/:plugin/pages/:pageRead a permitted extension admin page
/api/v1/extensions/:plugin/blocks/:name/renderValidate extension block values and generate its native fallback
/api/v1/public-extensions/:plugin/tokenIssue a same-origin expiring public submission token
/api/v1/extensions/:plugin/endpoints/:nameCall a declared extension endpoint with fresh permissions
/api/v1/public-extensions/:plugin/endpoints/:nameCall a rate-limited public extension endpoint
/api/v1/extensions/:plugin/endpoints/:nameCall a declared extension endpoint with fresh permissions
/api/v1/public-extensions/:plugin/endpoints/:nameCall a rate-limited public extension endpoint
/api/v1/extensions/:plugin/endpoints/:nameCall a declared extension endpoint with fresh permissions
/api/v1/public-extensions/:plugin/endpoints/:nameCall a rate-limited public extension endpoint
/api/v1/appearance/taxonomy-optionsList taxonomies for template targeting
/api/v1/seo/domainsRead configured canonical domain and trusted proxy policy
/api/v1/seo/redirectsList editorial redirects
/api/v1/seo/redirectsSave a redirect with a version precondition
/api/v1/seo/redirects/:id/removeRemove a versioned redirect
/api/v1/observabilityRead bounded process metrics and explicit error reporting status
/api/v1/languagesList verified interface languages
/api/v1/languages/catalogRead an installed catalog with a French fallback
/api/v1/account/localeRead the current user's interface preference
/api/v1/account/localeSet the current user's interface preference without changing site content
/api/v1/language-packsInstall or update an Ed25519 signed declarative language pack
/api/v1/language-packs/rollbackRestore the previous compatible signed catalog
/api/v1/language-packs/historyRead paginated language pack changes
/api/v1/pluginsInstall a verified extension package
/api/v1/plugins/:id/updateBack up then transactionally update an extension
/api/v1/plugin-updatesRead extension update and backup history
/api/v1/pluginsList installed plugin packages
/api/v1/plugins/:id/activateactivate a plugin
/api/v1/plugins/:id/deactivatedeactivate a plugin
/api/v1/plugins/:id/removeremove a plugin
/api/v1/plugins/:id/settingsRead plugin settings schema and values
/api/v1/plugins/:id/settingsSave validated plugin settings
/api/v1/bootstrapInstallation status
/api/v1/loginCreate a session
/api/v1/sessionCurrent user and CSRF token
/api/v1/logoutRevoke the current session
/api/v1/content-typesList registered content types
/api/v1/account/passwordChange own password and revoke all sessions
/api/v1/users/:idUpdate a versioned user and assigned roles
/api/v1/roles/:idUpdate a versioned custom role
/api/v1/roles/:id/removeRemove an unassigned custom role
/api/v1/content-typesRegister a content type and fields
/api/v1/contentSearch content with pagination
/api/v1/contentCreate content with its first revision
/api/v1/content/:idRead a content entry
/api/v1/content/:idSave content with a version precondition
/api/v1/content/:id/revisionsRead paginated revision history
/api/v1/content/:id/restore/:revisionRestore a revision into a new draft
/api/v1/mediaList image and PDF library
/api/v1/mediaValidate a PDF or re-encode an image with responsive variants
/api/v1/media/:idUpdate image accessibility metadata
/api/v1/settingsRead site settings
/api/v1/settings/home-optionsChoose a published home page
/api/v1/settingsSave validated site settings
/api/v1/usersList users without credential material
/api/v1/usersCreate a local user
/api/v1/users/:id/revokeRevoke every session for a user
/api/v1/rolesRead configurable roles
/api/v1/rolesCreate a role from granted permissions
/api/v1/permissionsRead registered permissions
/api/v1/healthRead measured site health
/api/v1/auditRead paginated administrative audit log
/api/v1/openapiRead the actual registered route contract