API REST
L'API REST du Labo du Yeti expose l'intégralité des fonctionnalités du CMS via des endpoints HTTP versionnés sous le préfixe /api. Toutes les routes sont servies par backend/src/server.js (Express ESM) et chaque router est isolé dans backend/src/routes/. Cette page documente l'ensemble des endpoints groupés par router, avec rôles requis, capabilities, exemples de payload, réponses et codes d'erreur typiques.
Content-Type: application/json. Les réponses suivent le format { ok: true, ... } en cas de succès et { ok: false, error: "code", message: "..." } en cas d'erreur. Les dates sont au format ISO 8601.
Authentification globale
Deux mécanismes d'authentification cohabitent :
- JWT — cookie HttpOnly émis par
POST /api/auth/login, valide pour le panneau d'administration React. - Tokens API — format
cmstok_*hashé en SHA-256, envoyés via headerAuthorization: Bearer cmstok_xxxpour les appels machine-to-machine, reporting et MCP.
Le middleware requireAuth (backend/src/middleware/auth.js) accepte les deux. requireRole(...) et requireCapability(featureId) sont chaînés ensuite pour le contrôle d'accès granulaire. Voir Authentification & RBAC.
Rate limits
Quatre niveaux de rate limiting sont actifs :
| Limiter | Cible | Quota |
|---|---|---|
| Global | Toutes routes API | 600 req/min/IP |
loginLimiter | /auth/login, /auth/2fa/*, /auth/password-reset/* | 10 req/min/IP |
aiGenLimiter | Générations IA (cocon, blog, articles) | 10 req/min/IP |
restoreLimiter | /backup/restore | 1 req/min/IP |
submitLimiter | /forms/:formId (soumissions publiques) | 10 req/min/IP |
Le dépassement renvoie 429 Too Many Requests avec un header Retry-After.
Codes d'erreur communs
| Code | Signification | Cas typiques |
|---|---|---|
400 | Bad Request | Payload invalide, champ requis manquant |
401 | Unauthorized | JWT absent/expiré, token API invalide |
403 | Forbidden | Rôle insuffisant, capability désactivée |
404 | Not Found | Ressource inexistante |
409 | Conflict | Slug déjà pris, conflit optimistic locking |
412 | Precondition Failed | if_updated_at obsolète (concurrent edit) |
429 | Too Many Requests | Rate limit dépassé |
500 | Server Error | Erreur interne (consulter logs) |
/api/auth — Authentification
Géré par backend/src/routes/auth.js avec le service backend/src/services/auth-service.js. Cycle complet : bootstrap initial, login, 2FA email, password reset 3-étapes, gestion des admins et tokens API.
GET /api/auth/status
GET Public. Renvoie l'état d'initialisation du CMS.
{ "ok": true, "bootstrapped": true, "two_factor_enabled": false }
POST /api/auth/bootstrap
POST Public, rate limit 10/min. Crée le premier compte owner (un seul appel possible).
curl -X POST https://example.com/api/auth/bootstrap \
-H "Content-Type: application/json" \
-d '{"fullname":"Jean Dupont","username":"admin","email":"admin@example.com","password":"S3cur3!Pass"}'
Erreurs : 409 si déjà bootstrappé, 400 si payload invalide.
POST /api/auth/login
POST Public, rate limit 10/min. Accepte email ou username.
{ "login": "admin@example.com", "password": "S3cur3!Pass" }
Réponse 200 : { ok: true, requires_2fa: false, user: { id, role, ... } }. Si 2FA activée, renvoie { ok: true, requires_2fa: true, challenge_id }. Erreurs : 401 credentials invalides, 429 trop de tentatives.
POST /api/auth/2fa/verify
POST Public, rate limit 10/min. Vérifie le code 6 chiffres envoyé par email.
{ "challenge_id": "uuid", "code": "123456" }
POST /api/auth/password-reset/{request,verify,confirm}
POST Cycle 3-étapes : request (email cible), verify (token reçu par mail), confirm (nouveau mot de passe). Rate limit 10/min sur chaque étape.
GET /api/auth/me
GET Auth requise. Retourne le profil courant : { id, fullname, username, email, role, last_login_at }.
CRUD /api/auth/admins
- GET
/admins— liste tous les comptes (auth requise). - POST
/admins— création (rôles : owner, admin, webmaster). - PUT
/admins/:id— édition (vérifications role côté controller). - DELETE
/admins/:id— suppression (rôles : owner, admin uniquement).
owner peut modifier le rôle d'un autre utilisateur ou supprimer un autre owner. Voir RBAC pour la matrice complète.GET / PUT /api/auth/security
Lecture (owner, admin) et mutation (owner uniquement) de la config sécurité : mode développement, activation 2FA globale.
/api/auth/tokens
Capability settings_tokens requise (owner et admin par défaut).
curl -X POST https://example.com/api/auth/tokens \
-H "Authorization: Bearer cmstok_existing" \
-d '{"name":"CI/CD","scopes":"read","expires_at":"2027-01-01T00:00:00Z"}'
Réponse : { ok: true, token: "cmstok_NEW_RAW", id: "..." }. Le token brut est retourné une seule fois.
/api/pages — Pages statiques
Router : backend/src/routes/pages.js, service : backend/src/services/pages-service.js. Capability pages requise.
- GET
/api/pages/library— templates HTML disponibles. - GET
/api/pages/library/:name— un template précis. - GET
/api/pages— liste des pages. - GET
/api/pages/:id— détail d'une page. - GET
/api/pages/:id/template— template brut. - GET
/api/pages/:id/preview— rendu HTML avec layout actif. - POST
/api/pages— création (multipart : template HTML + métadonnées). - PUT
/api/pages/:id— édition (slug, title, overrides, status). - PUT
/api/pages/:id/template— remplacement du template. - DELETE
/api/pages/:id— suppression.
Mutations réservées aux rôles owner, admin, webmaster, editor. Verrouillage optimiste via if_updated_at dans le body PUT : retourne 412 Precondition Failed si la version locale est obsolète.
{
"slug": "a-propos",
"title": "À propos",
"status": "published",
"if_updated_at": "2026-05-26T10:30:00Z",
"overrides": { "hero.title": "Bienvenue" }
}
/api/blog — Blog
Router : backend/src/routes/blog.js. Capability blog requise sur l'ensemble des endpoints.
Config & taxonomies
- GET
/config— PUT/config(owner, admin, webmaster) — réglages globaux blog. - GET
/categories, POST, PUT/:id, DELETE/:id. - GET
/tags, POST, DELETE/:id.
Articles
- GET
/articles— liste paginée (filtres : status, category, tag, q). - GET
/articles/:id— détail. - GET
/articles/:id/template— template HTML brut. - GET
/articles/:id/preview— rendu HTML. - POST
/articles— création (multipart, upload template). - PUT
/articles/:id— édition. - PUT
/articles/:id/template— replacement du HTML. - DELETE
/articles/:id— suppression. - POST
/articles/:id/generate— génération IA du contenu (aiGenLimiter 10/min). - POST
/articles/:id/regenerate-image— featured image via banque (Unsplash/Pexels/Pixabay).
curl -X POST https://example.com/api/blog/articles/abc123/generate \
-H "Authorization: Bearer cmstok_xxx" \
-d '{"prompt_extras":"Ton expert, 1200 mots","model":"claude-opus"}'
Réponse { ok: true, article: { ..., status: "draft", ai_usage: { input_tokens, output_tokens } } }.
Prévisualisations & templates globaux
- GET
/preview/index,/preview/category/:slug,/preview/tag/:slug. - GET
/library, POST/templates/upload, GET/template-defaults(owner, admin, webmaster).
/api/cocon — Cocon SEO
Router : backend/src/routes/cocon.js, service : backend/src/services/cocon-service.js. Capability cocon requise. Pages parent/enfants, variables cartésiennes, quota 5 pages/7j configurable.
Content groups
- GET
/groups,/groups/:id,/groups/:id/template,/groups/:id/combinations. - GET
/groups/:id/generation-progress— état temps-réel d'un batch IA. - GET
/groups/:id/quota-status— décompte créneaux libres. - PUT
/groups/:id/quota— réglage quota (mutations editor+). - POST
/groups— création (upload template HTML). - PUT
/groups/:id, PUT/groups/:id/template, DELETE/groups/:id. - POST
/groups/:id/generate— génération batch IA (aiGenLimiter 10/min). - DELETE
/groups/:id/pages— purge toutes les pages générées d'un groupe.
Pages générées
- GET
/pages,/pages/:id,/pages/:id/template,/pages/:id/preview. - PUT
/pages/:id, DELETE/pages/:id.
Médias & preview token
- GET
/media, POST/media, PUT/media/:id, DELETE/media/:id. - POST
/preview-token— token court éphémère pour iframe du Builder. - GET
/counts— décompte global (groupes + pages).
409 avec error: "quota_exhausted" et next_slot_at. Notifications email aux rôles admin + webmaster 5 min après chaque créneau libéré./api/media — Médiathèque centrale
Router : backend/src/routes/media.js, capability media.
- GET
/api/media— liste (filtres : q, type, mois, année). - POST
/api/media— upload (multipart, champfile). - DELETE
/api/media/:name— suppression.
Mutations ouvertes aux rôles owner, admin, webmaster, editor. Conversion WebP automatique si l'extension webp-auto-converter est active.
/api/forms — Formulaires
Router : backend/src/routes/forms.js, capability forms. Auto-détection des <form data-cms-form> dans les templates.
- GET
/api/forms/runtime.js— public, embed JS pour soumissions front. - GET
/api/forms/detect— formulaires détectés dans le HTML. - GET
/api/forms/config,/config/:formId. - PUT
/api/forms/config/:formId— destinataires email, webhook, anti-spam. - DELETE
/api/forms/config/:formId. - POST
/api/forms/config/:formId/test— envoi de test. - POST
/api/forms/:formId— soumission publique (submitLimiter 10/min, regex[a-z0-9][a-z0-9_-]*).
/api/ai — Configuration IA
Router : backend/src/routes/ai.js, capability settings_ai, rôles owner + admin uniquement.
- GET
/api/ai/status— état des providers (clés présentes, modèles dispos). - GET
/api/ai/config, PUT/api/ai/config— API keys (OpenAI, Anthropic), modèles par défaut, pricing. - GET
/api/ai/usage— agrégats consommation (jour, kind, provider). - GET
/api/ai/usage/export.csv— export détaillé CSV (aiCallLimiter 10/min).
{
"openai": { "api_key": "sk-...", "default_model": "gpt-4o-mini" },
"anthropic": { "api_key": "sk-ant-...", "default_model": "claude-opus" },
"default_provider": "anthropic"
}
/api/images — Banques d'images
Router : backend/src/routes/images.js, capability settings_apis.
- GET / PUT
/api/images/config— Unsplash / Pexels / Pixabay (owner, admin). - POST
/api/images/search— test recherche (tous rôles authentifiés).
/api/search — Recherche web
Router : backend/src/routes/search.js. Configuration des providers (Brave, SerpAPI, Tavily) pour sourcing d'articles.
- GET / PUT
/api/search/config— capabilitysettings_apis, owner+admin. - POST
/api/search/test— test recherche libre. - GET
/api/search/suggest-titles— suggestions de titres d'article. - GET
/api/search— recherche web brute (debug).
/api/build — Build & sitemap
Router : backend/src/routes/build.js, capability build.
- GET
/api/build/status— état du dernier build. - GET
/api/build/sitemap— liste sitemap. - POST
/api/build— lancebuildSite()(owner, admin, webmaster). - POST
/api/build/sitemap— régénération sitemap.xml seul.
curl -X POST https://example.com/api/build \
-H "Authorization: Bearer cmstok_xxx"
Réponse : { ok: true, generated: { pages: 42, articles: 18, cocon: 120 }, duration_ms: 3120 }. Voir Build & Publication.
/api/layouts — Layouts globaux
Router : backend/src/routes/layouts.js, capability layouts. Templates HTML appliqués à toutes les pages (header, footer, structure).
- GET
/api/layouts— liste. - GET
/api/layouts/active— layout actif. - GET
/api/layouts/:name— détail. - POST
/api/layouts— upload (owner, admin, webmaster). - PUT
/api/layouts/active— activation. - DELETE
/api/layouts/:name— suppression.
/api/global — Config globale
Router : backend/src/routes/global.js. Paramètres du site (nom, logo, slogan), header, footer, thème, SMTP.
- GET
/api/global— config complète. - GET
/api/global/layout-fields— champs dynamiques détectés dans le layout actif. - GET
/api/global/smtp— statut SMTP (test connexion). - PUT
/api/global/header, PUT/api/global/footer— capabilityheader_footer. - PUT
/api/global/theme— éditable par editor. - PUT
/api/global— patch générique (controller bloqueeditorsur SMTP, branding sidebar, IA, images). - PUT
/api/global/site— nom, logo, slogan, locales. - PUT
/api/global/smtp— config SMTP (owner, admin, webmaster).
/api/extensions — Système d'extensions
Router : backend/src/routes/extensions.js, capability extensions, rôles owner/admin/webmaster pour mutations. Marketplace install ZIP (max 10 MB).
- GET
/api/extensions— liste installées. - GET
/api/extensions/menu— entrées sidebar dynamiques. - GET
/api/extensions/:id,/api/extensions/:id/settings. - POST
/api/extensions/inspect— inspecte un ZIP (manifest, permissions) avant install. - POST
/api/extensions— installation effective. - PUT
/api/extensions/:id/activate,/api/extensions/:id/deactivate. - PUT
/api/extensions/:id/settings— config UI. - DELETE
/api/extensions/:id— désinstallation.
Les routes propres aux extensions actives sont exposées sous /api/ext/<id>/.... Voir Système d'extensions.
/api/capabilities — Matrice RBAC
Router : backend/src/routes/capabilities.js. Matrice rôle × feature, mutations réservées à owner.
- GET
/api/capabilities— matrice effective (tous rôles auth). - PUT
/api/capabilities— set overrides (owner). - POST
/api/capabilities/reset— retour aux défauts (owner).
/api/backup — Sauvegarde & restauration
Router : backend/src/routes/backup.js, capability settings_security, rôle owner exclusivement.
- GET
/api/backup/export— télécharge un ZIP complet (DB, médias, extensions, brouillons). - POST
/api/backup/restore— restauration (multipart ZIP, max 200 MB, restoreLimiter 1/min). - GET
/api/backup/list— safety backups locaux générés avant chaque restore.
POST /restore remplace la totalité du contenu. Une safety backup automatique est créée avant l'écrasement et listée par /list. Zip slip guard actif (refus des chemins remontants)./api/logs — Audit
Router : backend/src/routes/logs.js, capability logs.
- GET
/api/logs— pagination DB (filtres :type,action,q,since,limit,offset).
curl "https://example.com/api/logs?type=user_login&limit=50" \
-H "Authorization: Bearer cmstok_xxx"
/api/health, /api/version, /api/stats, /api/branding
Endpoints système servis depuis backend/src/server.js (hors router dédié).
- GET
/api/health— public, ping uptime{ ok: true, uptime: 12345 }. - GET
/api/branding— public, données filtrées pour écran Login (nom, logo, slogan). - GET
/api/version— auth requise, version + snapshot stats. - GET
/api/stats— auth (JWT ou token API), statistiques du site (pages, articles, cocon, build, IA).
Ces endpoints alimentent la plateforme de reporting cross-sites via token API cmstok_*.
/api/ext — Routes d'extensions
Racine dynamique : chaque extension active expose ses routes sous /api/ext/<extension-id>/.... L'authentification et les capabilities sont déterminées par le manifest de l'extension (manifest.permissions). Les hooks events et filter sont enregistrés automatiquement au boot par le loader (extensions/installed/<id>).
Exemples curl complets
# Login + récupération du cookie JWT
curl -c cookies.txt -X POST https://example.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"login":"admin@example.com","password":"S3cur3!Pass"}'
# Lister les pages (cookie)
curl -b cookies.txt https://example.com/api/pages
# Créer un article via token API
curl -X POST https://example.com/api/blog/articles \
-H "Authorization: Bearer cmstok_xxx" \
-F "template=@./template.html" \
-F 'meta={"title":"Mon article","category_id":"abc"};type=application/json'
# Lancer un build
curl -X POST https://example.com/api/build \
-H "Authorization: Bearer cmstok_xxx"
# Exporter un backup
curl -OJ -H "Authorization: Bearer cmstok_xxx" \
https://example.com/api/backup/export
Pour aller plus loin
- Authentification & RBAC — matrice détaillée des rôles et capabilities.
- Base de données — schémas SQLite alimentés par ces endpoints.
- Système d'extensions — comment exposer ses propres routes
/api/ext/<id>. - Reporting — consommation des endpoints
/statset/versionen cron. - Sécurité — Helmet, CORS, rate limiting, audit logs.