Catalogue des statements

Dernière mise à jour : 23 juillet 2026

Chaque élément du tableau statements est un statement. Ce document catalogue les champs, le comportement et le résultat des 17 types de statement. Chaque emplacement de valeur suit les règles des Expressions de valeur (référence, littéral, JsonLogic, mappage de locale).

Résumé des statements

CatégorietypeRésumé en une ligne
Écritures de ressourceResourceCreateCréer un Content/Media (publication facultative)
ResourceUpdateRemplacement intégral des champs de Content/Media (tout champ/locale non fourni est supprimé)
ResourcePatchFusion partielle des champs de Content/Media (uniquement les champs/locales spécifiés ; un null littéral supprime)
ResourceDeleteSupprimer (Draft/Archived uniquement ; si Published, dépublier d'abord)
ResourcePublish / ResourceUnpublishPublier / dépublier
ResourceArchive / ResourceUnarchiveArchiver / désarchiver
Lectures de ressourceResourceReadLecture d'un seul élément par id
ResourceFindPremier élément correspondant via filtre (null si aucun)
ResourcePageReadLecture avec filtre/tri/pagination ({ items, next })
ExterneHttpAppel HTTP externe ({ status, body }). Async uniquement
VariablesSetVarDéclarer/mettre à jour une variable à portée script
Flux de contrôleIfBranchement conditionnel
LoopItération (foreach / while / counted)
ParallelExécution simultanée de branches
ReturnRenvoyer un résultat et terminer prématurément
TryGestion des exceptions (catch/finally)

Les appels cycliques sont limités à 3. Les instructions d'écriture de ressources ci-dessus (ResourceCreate, ResourceUpdate, ResourcePublish, etc.) déclenchent des événements de modification, et ces événements peuvent exécuter à nouveau un Script via un Webhook. Une telle chaîne (Script → événement → Webhook → Script → …) se poursuit au maximum 3 fois. Au-delà, la plateforme l'interrompt automatiquement pour éviter les boucles infinies.

Champs communs

{ "type": "<StatementType>", "name": "<facultatif, unique dans le script>", /* ...champs spécifiques au type... */ }
  • type : le discriminant. L'une des valeurs du tableau ci-dessus (obligatoire).
  • name : facultatif. Lorsqu'il est défini, le résultat est lié au contexte à /<name>, de sorte que les statements suivants peuvent le référencer via { /<name>/... }. On l'omet si l'on n'utilise pas le résultat.
  • Règles de nom de liaison : name (ainsi que le as d'un Loop) est une clé posée telle quelle à la racine du contexte ; elle est donc validée à l'enregistrement. Elle ne doit pas être une chaîne vide, ne doit pas contenir / ni ~ (afin de pouvoir servir de clé JSON Pointer), ne peut pas coïncider avec une racine réservée (payload, vars, error), et doit être unique au sein d'un même Script. En cas de violation, l'enregistrement est refusé avec respectivement WGL400033 (format), WGL400032 (mot réservé) et WGL400034 (doublon).

Forme des références d'entité

Les références d'entité comme contentType et target sont unifiées en une seule forme : { "sys": { "id": <expression de valeur> } }. Seul sys.id est nécessaire ; le type cible est déduit de resource (sys.type et sys.targetType sont omis).

  • contentType.sys.id est généralement un littéral (par ex. "ct_post").
  • target.sys.id est généralement une expression de valeur { /ptr } (résolue à l'exécution ; par ex. { /payload/sys/id }).

resource

Les statements de la famille ressource indiquent le type de cible avec resource: "Content" | "Media".

Écritures de ressource

Chaque statement d'écriture possède propagateEvents (par défaut false). Le mettre à true fait que cette écriture émet son propre EntityEvent (déclenchant des traitements en aval comme l'indexation de recherche ou les Webhook). Par défaut, il n'émet rien (une écriture système silencieuse).

ResourceCreate

Crée un Content ou un Media. Content et Media partagent le modèle fields, et les valeurs sont des mappages de locale.

ChampS'applique àDescription
resourceCommun"Content" ou "Media" (obligatoire)
contentTypeContentLe Content Type à créer ({ sys: { id } }). Obligatoire pour Content
fieldsCommunLe mappage de champs { "<field>": { "<locale>": valeur } }. Chaque champ renseigné requiert le bucket de la locale par défaut. Les clés de Content suivent la définition du Content Type ; les clés de Media sont fixes (title, description, file)
localeCommun(Commodité) Si fourni, enveloppe automatiquement chaque valeur de fields en { <locale>: valeur }
publishCommunPublie après l'écriture (exposé sur CDA/ACDA). Par défaut true
  • Media file : la valeur fields.file.{locale} est une instruction d'ingestion { "source": <expression de valeur>, "encoding": "url"|"base64" } (les deux sont obligatoires). Une écriture de Media qui inclut un fichier est Async uniquement (le moteur le traite en ligne en arrière-plan, puis le publie ; cela vaut pour url et base64). On peut aussi créer un Media sans fichier (fileless). Si publish:true mais qu'il n'y a pas de fichier ou que le traitement est incomplet, l'étape de publication échoue ; si publish:false, il reste Draft.
  • Résultat (liaison de name) : la ressource créée. { /<name>/sys/id }, { /<name>/fields/<field>/<locale> }.
// Content
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
  "fields": { "title": { "en-US": "{ /payload/fields/title }" } }, "publish": true, "name": "post" }
 
// Media. file est une instruction d'ingestion (Async uniquement)
{ "type": "ResourceCreate", "resource": "Media",
  "fields": {
    "title": { "en-US": "{ /payload/fields/prompt }" },
    "file":  { "en-US": { "source": "{ /gen/body/data/0/url }", "encoding": "url" } }
  }, "name": "img" }

ResourceUpdate

Remplace intégralement les champs du Content ou Media cible (PUT). Ce que l'on passe dans fields devient le nouvel ensemble de champs, et tout champ et locale absent ici est supprimé. Pour n'en changer qu'une partie, on utilise ResourcePatch.

ChampDescription
resource"Content" ou "Media"
targetLa cible ({ sys: { id } }, obligatoire). L'id est généralement { /ptr }
fieldsL'ensemble complet des champs à écrire. Les valeurs sont des mappages de locale. Comme il s'agit d'un remplacement intégral, tout champ et locale absent ici est supprimé. Pour un Media, file est une instruction d'ingestion (voir ResourceCreate ci-dessus) ; les fichiers listés sont toujours réingérés, et les fichiers des locales non fournies sont supprimés
locale(Commodité) Enveloppe automatiquement fields
version(Facultatif) Une expression de valeur (Int). Verrouillage optimiste. Si fournie, la mise à jour ne s'effectue que si elle correspond au sys.version actuel de la cible ; en cas de non-correspondance, elle abandonne avec une erreur de conflit de version (interceptable avec Try). Si omise, aucune vérification (last-write-wins)
publishRepublie après la mise à jour. Par défaut true

Si l'on utilise Update pour ne modifier que les métadonnées d'un Media, le file étant absent, tous les fichiers sont supprimés (puisqu'il s'agit d'un remplacement intégral). Pour une modification partielle, on utilise impérativement ResourcePatch. Un Update qui inclut un fichier est Async uniquement.

{ "type": "ResourceUpdate", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
  "fields": { "title": { "en-US": "Hello", "ko-KR": "안녕" }, "status": { "en-US": "published" } } }

ResourcePatch

Fusionne partiellement les champs du Content ou Media cible (PATCH). Écrase uniquement les champs (et les locales qu'ils contiennent) passés dans fields, et laisse intacts les champs et locales non mentionnés. La forme des valeurs, locale, version et publish sont identiques à ResourceUpdate.

ChampDescription
resource"Content" ou "Media"
targetLa cible ({ sys: { id } }, obligatoire). L'id est généralement { /ptr }
fieldsLes champs à écraser. Les valeurs sont des mappages de locale. Met à jour uniquement les champs et buckets de locale spécifiés (le reste est conservé). Si une valeur est un null littéral, ce couple (champ, locale) est supprimé. Pour un Media, file est une instruction d'ingestion (voir ResourceCreate ci-dessus)
locale(Commodité) Enveloppe automatiquement fields
version(Facultatif) Identique à ResourceUpdate (verrouillage optimiste)
publishRepublie après la mise à jour. Par défaut true
  • Supprimer une locale ou un fichier spécifique : on donne un null littéral comme valeur. Par ex. : "title": { "fr-FR": null } (supprime le titre fr-FR), "file": { "en-US": null } (supprime le fichier en-US). Une expression de valeur qui s'évalue à null au moment de l'exécution n'est pas une suppression mais une erreur (seul un null littéral supprime).
  • Donner une instruction d'ingestion au file d'un Media remplace le fichier de cette locale (Async uniquement). Si l'on ne fournit pas de fichier, il est conservé.
// +1 sur viewCount(en-US) uniquement. title, les autres locales, etc. sont conservés tels quels
{ "type": "ResourcePatch", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } },
  "fields": { "viewCount": { "en-US": { "+": [ "{ /payload/fields/viewCount }", 1 ] } } } }

ResourceDelete

Supprime la cible. Seuls les statuts Draft et Archived peuvent être supprimés. Si l'élément est Published ou Changed, la suppression est refusée : il faut donc d'abord ResourceUnpublish (pour un Media, elle est aussi refusée pendant que le fichier est en cours de traitement (busy)). Il ne dépublie pas automatiquement (comme CMA/ACMA).

ChampDescription
resource"Content" ou "Media"
targetLa cible ({ sys: { id } }, obligatoire)
{ "type": "ResourceDelete", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }

ResourcePublish, ResourceUnpublish, ResourceArchive, ResourceUnarchive

Contrôle indépendamment l'état de publication et d'archivage de la cible. Les quatre partagent les mêmes champs. La précondition de statut de chaque opération est identique à CMA/ACMA (publish impossible depuis Archived et nécessite que le traitement du fichier soit terminé ; unpublish uniquement depuis Published/Changed ; archive uniquement depuis Draft ; unarchive uniquement depuis Archived).

ChampDescription
resource"Content" ou "Media"
targetLa cible ({ sys: { id } }, obligatoire)
version(Facultatif) Une expression de valeur (Int). Verrouillage optimiste. Si fournie, l'opération ne s'effectue que si elle correspond au sys.version actuel
{ "type": "ResourcePublish",   "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceUnpublish", "resource": "Content", "target": { "sys": { "id": "{ /payload/sys/id }" } } }
{ "type": "ResourceArchive",   "resource": "Media",   "target": { "sys": { "id": "{ /m/sys/id }" } } }

Lectures de ressource

Les statements de lecture ne modifient pas l'état (pas de propagateEvents).

Les trois statements de lecture déterminent tous, via from (facultatif, Current par défaut), quelle copie stockée lire. Current est le dernier brouillon que voit le studio de contenu (la valeur que lisent CMA/ACMA), et Published est l'instantané publié (celui que distribuent CDA/ACDA, la valeur au moment de la dernière publication).

ResourceFind et ResourcePageRead peuvent en outre activer la Recherche avancée (Advanced Search) via advanced (facultatif, par défaut false). Réservée au Content, elle est ignorée pour les lectures de Media. Lorsqu'elle est activée, where peut utiliser les opérateurs regex, near et within ainsi que la recherche en texte intégral (sur un champ LongText dont la recherche en texte intégral est activée, eq trouve aussi les éléments qui contiennent la valeur, par correspondance partielle et approchée), et order peut trier par fields.*. Lorsqu'elle est désactivée, ces trois opérateurs sont rejetés, eq sur du texte est une correspondance exacte, et prefix ainsi que les opérateurs de comparaison et de liste fonctionnent indépendamment de la recherche avancée. Un élément qui vient d'être créé ou modifié met un court instant (environ 1 seconde) à apparaître dans la recherche avancée, si bien que la requête de recherche avancée qui suit immédiatement peut ne pas le renvoyer. Pour lire sans attendre un élément qui vient d'être écrit, utilisez ResourceRead par id (le stockage principal, sans délai d'apparition) ou interrogez par le sys.id renvoyé par l'écriture.

Dans where et order, un champ de contenu s'écrit fields.<field> (le nom seul n'est pas reconnu). À fields.<field>, le moteur applique automatiquement la locale par défaut du Space, si bien qu'on n'y ajoute pas de locale directement. Les fields.status et fields.slug des exemples ci-dessous interrogent donc directement la locale par défaut. Ce n'est que pour viser une locale précise (non par défaut) qu'on la spécifie avec fields.<field>.<locale> (par ex. fields.title.ko-KR). sys.* (comme sys.createdAt) et createdBy (:self) s'écrivent tels quels, sans fields.. Les règles détaillées figurent dans La locale dans where et order des Expressions de valeur.

ResourceRead

Une lecture d'un seul élément par id (get-by-id). Le résultat lie la ressource entière au nom.

ChampDescription
resource"Content" ou "Media"
targetLa cible ({ sys: { id } }). L'id est une expression de valeur
from(Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié)
  • Résultat : référencer directement { /<name>/sys/id } et { /<name>/fields/<field>/<locale> } (pas besoin de items/0).
  • Si la cible n'existe pas, cela génère une erreur. On peut l'envelopper dans un Try pour la gérer.
{ "type": "ResourceRead", "resource": "Content",
  "target": { "sys": { "id": "{ /payload/fields/orderId }" } }, "name": "order" }

ResourceFind

Lit le premier élément correspondant, via un filtre. S'il n'y en a aucun, c'est null. À utiliser pour trouver un enregistrement par une clé métier unique (slug, email, sku).

ChampDescription
resource"Content" ou "Media"
contentType(Content) Le Content Type dans lequel chercher ({ sys: { id } })
whereLe filtre ({ "<field>": { "<op>": <valeur> } }). Les opérateurs sont ceux de la liste des opérateurs (regex/near/within nécessitent advanced). createdBy: ":self" pris en charge
orderLe tri qui détermine le « premier » lorsque plusieurs correspondent (par ex. "-sys.createdAt")
from(Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié)
advanced(Facultatif) Exécuter via la recherche avancée. Content uniquement (Media est ignoré). Par défaut false. Voir la note Lectures de ressource ci-dessus.
  • Résultat : lie la première ressource correspondante au nom. On la référence directement via { /<name>/fields/<field>/<locale> }. Comme elle vaut null en l'absence de résultat, on branche selon l'existence avec { "==": [ "{ /<name> }", null ] } (le schéma classique du find-then-upsert).
{ "type": "ResourceFind", "resource": "Content", "contentType": { "sys": { "id": "ct_article" } },
  "where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }, "name": "found" }

ResourcePageRead

Une lecture avec filtre, tri et pagination.

ChampDescription
resource"Content" ou "Media"
contentType(Content) Le Content Type dans lequel chercher
whereLe filtre ({ "<field>": { "<op>": <valeur> } }). Les opérateurs sont ceux de la liste des opérateurs (regex/near/within nécessitent advanced). createdBy: ":self" pris en charge
orderLe tri (par ex. "-sys.createdAt")
limitLa taille de page (100 ou moins)
cursorPour la page suivante, le next du résultat précédent
from(Facultatif) Current (par défaut, dernier brouillon) ou Published (instantané publié)
advanced(Facultatif) Exécuter via la recherche avancée. Content uniquement (Media est ignoré). Par défaut false. Voir la note Lectures de ressource ci-dessus.
  • Résultat : { items, next }. { /<name>/items/0/... }, et la page suivante est { /<name>/next }.
  • Pour parcourir l'ensemble, on utilise Loop while "{ /vars/hasMore }" avec cursor et l'accumulation par SetVar (voir le Cookbook).
{ "type": "ResourcePageRead", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
  "where": { "fields.status": { "eq": "draft" } }, "order": "-sys.createdAt", "limit": 100, "name": "page" }

Externe

Http

Appelle un endpoint HTTP externe. Lorsque Http est présent, executionMode doit valoir Async (ExternalIo).

ChampDescription
method"GET", "POST", "PUT", "PATCH", "DELETE"
urlL'URL cible (une expression de valeur ; { /ptr } peut y être inséré)
headers[{ "key", "value", "secret"? }]. value est une expression de valeur. Un en-tête secret:true est traité comme réservé à CMA (administrateur) : il n'est pas exposé aux utilisateurs finaux et n'est déchiffré que juste avant l'envoi de la requête
bodyLe corps de la requête (une expression de valeur ou du JSON)
timeoutMsLe délai d'expiration de cet appel (ms)
retryLe nombre de nouvelles tentatives lorsque le statut de la réponse est supérieur ou égal à 400. Par défaut 0 ; le plafond est maxHttpRetry (2 par défaut)
ignoreStatusCodeIndique s'il faut traiter cet appel comme un échec lorsque le statut final (après les nouvelles tentatives) est supérieur ou égal à 400. Lorsque false (par défaut), il est traité comme un échec et devient une cible de Try/catch. Lorsque true, il n'est pas traité comme un échec et { status, body } est lié tel quel (l'appelant branche lui-même sur status)
  • Résultat : { status, body }. { /<name>/status }, { /<name>/body/... }.
  • Limite de taille de réponse : le corps de la réponse est de 10MiB au maximum. S'il dépasse cette taille, cet appel échoue avec une exception et peut être géré comme n'importe quel autre échec d'exécution avec Try/catch (il s'agit d'un échec basé sur la taille, il n'est donc pas ignoré par ignoreStatusCode).
{ "type": "Http", "method": "POST", "url": "https://api.llm.com/v1/gen",
  "headers": [ { "key": "Authorization", "value": "Bearer sk-...", "secret": true } ],
  "body": { "prompt": "{ /payload/fields/prompt }" }, "timeoutMs": 15000, "retry": 1, "name": "resp" }

Variables

SetVar

Déclare ou met à jour une variable mutable à portée du script. On la référence via { /vars/<var> } (JsonLogic n'a pas de déclaration de variable, c'est donc fourni sous forme de statement).

ChampDescription
varLe nom de la variable. Référencée via { /vars/<var> }
valueUne expression de valeur. Elle peut se référencer elle-même pour accumuler
{ "type": "SetVar", "var": "total", "value": 0 }
{ "type": "SetVar", "var": "total", "value": { "+": [ "{ /vars/total }", "{ /row/qty }" ] } }   // accumulation
{ "type": "SetVar", "var": "ids",   "value": { "merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] } }  // collecte dans un tableau

Flux de contrôle

If

Un branchement conditionnel. condition est du JsonLogic, et l'évaluation en vrai ou faux suit les règles de Valeurs vraies et fausses.

ChampDescription
conditionJsonLogic (évalué comme un booléen)
thenLe tableau de statements à exécuter si vrai
else(Facultatif) Le tableau de statements à exécuter si faux
{ "type": "If",
  "condition": { "<": [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] },
  "then": [ { "type": "Return", "value": { "ok": false, "reason": "crédit insuffisant" } } ],
  "else": [ /* ... */ ] }

Loop

Une itération. On choisit un seul mode : over (foreach), while (condition) ou for (compté). Quel que soit le mode, le moteur impose une limite supérieure avec maxIterations (pour éviter les boucles infinies). Les appels externes à l'intérieur du body (Http, ingestion de fichier Media) sont interdits.

ChampDescription
overforeach : une expression de valeur qui se résout en un tableau
whilecondition : JsonLogic (répète tant que c'est vrai)
forcompté : { "from", "to", "step"? }. De from à to inclus ; step vaut 1 par défaut
maxIterationsLe nombre maximal d'itérations imposé par le moteur (obligatoire)
asLe nom auquel lier l'élément ou l'index courant ({ /<as> })
bodyLe tableau de statements du corps de la boucle
// foreach
{ "type": "Loop", "over": "{ /payload/fields/items }", "as": "item", "maxIterations": 100,
  "body": [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_item" } },
             "fields": { "name": { "en-US": "{ /item/name }" } } } ] }
 
// while
{ "type": "Loop", "while": "{ /vars/hasMore }", "maxIterations": 1000, "body": [ /* ... */ ] }
 
// counted (1..10 step 2)
{ "type": "Loop", "for": { "from": 1, "to": 10, "step": 2 }, "as": "i", "maxIterations": 100, "body": [ /* ... */ ] }

Parallel

Exécute les branches simultanément et poursuit après leur jonction. Les références entre branches ne sont pas autorisées (en cas de dépendance, on les place séquentiellement).

ChampDescription
branchesStatement[][]. Chaque élément est une branche (un tableau de statements)
{ "type": "Parallel", "branches": [
  [ { "type": "Http", "method": "GET", "url": "https://api.a.com/x", "name": "a" } ],
  [ { "type": "Http", "method": "GET", "url": "https://api.b.com/y", "name": "b" } ]
] }

Return

C'est le return de la programmation classique. Il renvoie le résultat du Script à l'appelant et se termine normalement à ce point.

ChampDescription
value(Facultatif) L'expression de valeur à renvoyer
isErrorPar défaut false. Si true, value ressort comme le error de la réponse (sinon comme return)
statusCodeLe code de statut de la réponse. Par défaut 200
  • Si Return n'est jamais atteint, il n'y a pas de valeur de retour. Pour renvoyer un résultat, on précise explicitement value.
  • Comme il s'agit d'une terminaison normale, et non d'une exception ou d'un throw, ce n'est pas une cible de catch (même à l'intérieur d'un Try, il termine l'intégralité du Script, mais finally s'exécute tout de même).
  • Un guard s'exprime aussi avec ce statement : If combiné à then:[Return] (renvoyer lorsque la condition est violée, de sorte que la suite ne s'exécute pas). C'est l'un de ses nombreux usages.
{ "type": "Return", "value": { "orderId": "{ /order/sys/id }", "status": "paid" }, "statusCode": 201 }
{ "type": "Return", "value": { "reason": "échec du paiement" }, "isError": true, "statusCode": 402 }

Try

Gestion des exceptions.

ChampDescription
bodyLe tableau de statements à tenter
catch(Facultatif) S'exécute en cas d'échec de body. Expose { message, statement } sur /error
finally(Facultatif) S'exécute toujours, que ce soit en cas de succès ou d'échec
  • Si catch la gère, le Script n'est pas interrompu. Seul un échec sans catch interrompt le Script (y compris la tentative de compensation).
  • Ce qui compte comme un « échec », ainsi que les limites de la compensation, sont traités dans Sémantique d'exécution, contraintes et sécurité.
{ "type": "Try",
  "body":    [ { "type": "Http", "method": "POST", "url": "https://primary.api/gen", "name": "resp" },
               { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
                 "fields": { "text": { "en-US": "{ /resp/body/text }" } } } ],
  "catch":   [ { "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_result" } },
                 "fields": { "text": { "en-US": "Échec de la génération" }, "error": { "en-US": "{ /error/message }" } } } ],
  "finally": [ /* toujours exécuté */ ] }