#Thèmes
Un site a plusieurs thèmes et un seul publié — celui que voient ses
visiteurs. Les quatre méthodes de /api/themes couvrent tout ce qui arrive à un
thème dans sa vie : naître, se faire copier, changer de nom, monter en ligne,
disparaître. Le contenu, lui, se manipule fichier par fichier depuis
Fichiers.
Toutes les opérations portent sur le site résolu — celui de
X-Webcosa-Site-Cible, ou le premier accessible. Un identifiant de thème qui
n’appartient pas à ce site répond 404 introuvable, jamais 403 : distinguer
« n’existe pas » de « appartient à quelqu’un d’autre » confirmerait à un curieux
que l’uuid deviné existe bien quelque part.
#Lister
/api/themes{
"site": {
"id": "9f2c4a11-0d38-4e77-b6c2-5f9a13d8e401",
"slug": "atelier-durand",
"nom": "Atelier Durand"
},
"themes": [
{
"id": "11111111-1111-4111-8111-111111111111",
"nom": "Origo",
"version": "1.0.0",
"role": "publie",
"origine": "origo",
"maj_le": "2026-08-05T09:12:44.108Z"
},
{
"id": "22222222-2222-4222-8222-222222222222",
"nom": "Origo (copie)",
"version": "1.0.0",
"role": "brouillon",
"origine": "origo",
"maj_le": "2026-08-04T17:02:11.740Z"
}
]
}{ "error": "no_site" }Portée lecture suffit. Le thème publié vient en tête : c’est celui qu’on
vient voir en premier. Les brouillons suivent, du plus récemment modifié au plus
ancien.
siteobjetLe site réellement résolu, avec son id, son slug et son nom. Présent à
chaque appel, et pas par confort : sans en-tête de désignation, la clé retient le
premier site accessible, un ordre qui change le jour où un site s’ajoute au
compte. Le CLI inscrit ce champ dans son .webcosa.json pour ne plus jamais
dépendre de cet ordre.
themes[].iduuidL’identifiant du thème, celui qu’attendent toutes les autres routes.
themes[].nomchaîneJusqu’à 80 caractères. Modifiable par PATCH.
themes[].versionchaîneCelle déclarée par le thème d’origine, recopiée à l’installation. L’API ne la modifie jamais — c’est une étiquette, pas un compteur.
themes[].rolepublie | brouillonpublie pour le thème servi aux visiteurs, brouillon pour tous les autres. Un
site n’a qu’un publie à la fois, garanti par un index en base et non par le
code applicatif.
themes[].originechaîne ou nullL’identifiant du thème du catalogue dont celui-ci descend — origo, forge,
vela, piazza. null pour un thème importé : l’import efface la filiation,
parce que laisser croire à des mises à jour qui ne viendront jamais serait pire
que de ne rien dire.
themes[].maj_lehorodatageRéécrite à chaque écriture de fichier et à chaque publication. C’est elle qui ordonne la liste.
#Installer un thème du catalogue
/api/themesCorps de la requête
{ "action": "installer", "origine": "origo" }{ "ok": true, "themeId": "33333333-3333-4333-8333-333333333333" }{ "error": "theme_inconnu" }{
"error": "site_inactif",
"etat": "expire",
"message": "Ce site n'est plus actif : ses modifications sont bloquées. Reprends un abonnement depuis le CMS (Réglages → Abonnement)."
}{ "error": "portee_insuffisante" }actioninstallerrequisDistingue les deux formes acceptées par cette route. installer et dupliquer
n’ont aucun champ en commun, d’où deux formes plutôt qu’un champ optionnel.
originechaînerequisL’identifiant d’un thème du catalogue, de 1 à 40 caractères. Quatre valeurs
existent aujourd’hui : origo, forge, vela, piazza.
curl -s -X POST https://cms.webcosa.com/api/themes \-H "Authorization: Bearer $WEBCOSA_CLE" \-H "X-Webcosa-Site-Cible: atelier-durand" \-H "Content-Type: application/json" \-d '{"action":"installer","origine":"forge"}'{"ok":true,"themeId":"33333333-3333-4333-8333-333333333333"}Installer ne publie pas. Le thème arrive en brouillon, et il faut un second
geste — le PATCH ci-dessous — pour qu’il remplace celui que voient les
visiteurs. On installe pour regarder ; publier d’office changerait le site public
d’un client au moment où il explore, et il n’y a pas de bouton « annuler » pour
ses visiteurs.
#Dupliquer
/api/themesCorps de la requête
{ "action": "dupliquer", "id": "11111111-1111-4111-8111-111111111111" }{ "ok": true, "themeId": "44444444-4444-4444-8444-444444444444" }{ "error": "introuvable" }{ "error": "fichier_requis_manquant", "message": "Il manque un fichier indispensable. Attendus : layout/theme.liquid, config/settings_schema.json, templates/index.json." }La copie reprend la version et l’origine de la source, et prend son nom suivi de
(copie). Elle arrive en brouillon, comme tout thème installé.
C’est le geste qui rend l’édition de code sans danger : on travaille sur une copie, on regarde, et on publie quand on est content. Le CLI le propose de lui-même quand on tente de suivre un thème publié.
id doit être un uuid bien formé — un identifiant court de huit caractères,
comme celui qu’affiche theme lister, vaut 400 invalid_input. Le raccourci est
une commodité du CLI, qui le résout avant d’appeler l’API ; l’API, elle, ne
devine rien.
#Renommer et publier
/api/themesCorps de la requête
{ "id": "22222222-2222-4222-8222-222222222222", "nom": "Atelier v2", "publier": true }{ "ok": true }{ "error": "introuvable" }{ "error": "publication_impossible" }iduuidrequisLe thème visé. Confronté au site avant toute action.
nomchaîneDe 1 à 80 caractères, espaces de bordure retirés. Appliqué en premier, pour qu’un appel qui renomme et publie d’un coup mette en ligne le thème déjà renommé.
publierbooléentrue met le thème en ligne et démet celui qui l’était.
false ne fait rien — il n’existe aucune façon de dépublier. C’est
volontaire : un site sans thème publié n’affiche plus rien. On remplace un thème
en ligne par un autre, on ne l’éteint pas.
Les deux champs sont facultatifs : un corps réduit à id répond 200 ok sans
rien changer. C’est sans conséquence, mais ce n’est pas une confirmation que le
thème existe — ça, c’est le 404 qui le dit.
Un uuid mal recopié dans publier aurait pu éteindre le site. La publication
démet d’abord le thème publié, puis promeut l’identifiant demandé : avec un
identifiant étranger au site, la première moitié réussissait et la seconde ne
trouvait rien — le site se retrouvait sans thème publié.
C’est la raison pour laquelle l’appartenance est vérifiée par une lecture
distincte, avant d’agir, et pas seulement par les filtres des mises à jour qui
suivent. Un update qui ne touche aucune ligne ne rend aucune erreur.
Publier fait aussi naître une page d’accueil si le site n’en a pas encore. Publier, c’est mettre le site en ligne ; sans page d’accueil, l’écran « Pages » reste vide, le référencement n’a nulle part où poser un titre, et il n’y a rien à ouvrir dans l’éditeur. L’échec de cette création ne fait pas échouer la publication — un thème bien en ligne ne doit pas être annulé par une page manquante.
curl -s -X PATCH https://cms.webcosa.com/api/themes \-H "Authorization: Bearer $WEBCOSA_CLE" \-H "Content-Type: application/json" \-d '{"id":"22222222-2222-4222-8222-222222222222","publier":true}'{"ok":true}#Retirer
/api/themes?id=<uuid>{ "ok": true }{ "error": "invalid_input" }{ "error": "introuvable" }{
"error": "theme_publie",
"message": "Ce thème est celui que voient tes visiteurs. Publie-en un autre avant de le retirer."
}Le thème publié ne se supprime pas. Ce serait éteindre l’apparence du site en un appel, sans rien pour la remplacer. Il faut d’abord en publier un autre — ce qui est exactement le geste qu’on veut forcer.
La suppression emporte les fichiers du thème avec elle, et il n’y a ni corbeille ni version précédente. Exportez avant, si le doute existe : voir Import et export.
C’est la seule écriture de cette section qui n’exige pas que le site soit actif. Retirer un brouillon ne change rien à ce que voient les visiteurs, et un site en fin d’essai peut encore faire le ménage chez lui. Le thème publié, lui, reste protégé par la garde ci-dessus.
#L’ordre des contrôles
Il compte, parce qu’il décide de l’erreur qu’on reçoit quand plusieurs sont vraies à la fois.
| Rang | Contrôle | Refus |
|---|---|---|
| 1 | Clé valable | 401 unauthorized |
| 2 | Portée suffisante | 403 portee_insuffisante |
| 3 | Le compte a au moins un site | 409 no_site |
| 4 | Site demandé accessible | 403 site_interdit |
| 5 | Site actif — POST et PATCH seulement | 402 site_inactif |
| 6 | Corps conforme | 400 invalid_input |
| 7 | Le thème est bien du site | 404 introuvable |
Un site dont l’essai est terminé répond donc 402 même si le corps de la requête
est absurde : la facturation est vérifiée avant la forme.

