Workflows
Valider et publier
Valider un workflow avant de le publier : lire les anomalies bloquantes et non bloquantes, utiliser le contrat de payload, et contrôler la publication et le retrait.
Un workflow ne génère de documents qu'une fois publié. Entre les deux se trouve la validation : un contrôle en lecture seule qui vous dit exactement ce qui ne va pas, avant que vous ne demandiez à l'API de publier et vous fassiez refuser.
Les workflows sont en bêta privée, disponible sur demande à [email protected] ; voir Workflows.
Valider
Lit l'état actuel du workflow. Il n'écrit jamais rien. L'appeler à répétition, ou pendant qu'un autre éditeur détient le verrou du constructeur, est toujours sans danger.
curl https://app.doclift.io/api/v1/workflows/templates/100050/validate \
--request POST \
--header "X-Api-Key: <your-api-key>" \
--header "Content-Type: application/json" \
--data '{}'
{
"publishable": false,
"anomalies": [
{
"type": "broken_reference",
"blocking": true,
"variable": "investor_name",
"section": { "id": 8823, "title": "Introduction", "kind": "rich_content" }
},
{
"type": "missing_background",
"blocking": false,
"variable": null,
"section": { "id": 8830, "title": "Cover", "kind": "image_with_variable" }
}
],
"sanitisation": [],
"stored": {
"inert_tokens": [],
"unreachable_images": [],
"clipped_bands": [],
"unused_variables": ["country_code"],
"layout_tables": [],
"palette": ["#1a1a1a", "#0057ff"],
"page_breaks": { "declared": [8825], "sections": 6, "content_length": 4210 },
"typography": {
"sizes_pt": [12, 14, 18],
"weights": [400, 700],
"sizes_off_the_editor_scale": [],
"weights_no_family_carries": []
},
"last_render": { "at": "2026-07-30T09:12:00+02:00", "stale": true }
}
}
Le corps porte trois lectures indépendantes du même workflow, toutes calculées contre la même arborescence enregistrée que lisent la génération et la publication :
| Clé | Ce qu'elle vous dit |
|---|---|
| publishable | Si POST .../publication accepterait le workflow en l'état (exactement la même règle, lue à l'avance). |
| anomalies | Les problèmes structurels dans l'arborescence enregistrée : références cassées, contradictions, un document vide. Chacune a un type, un indicateur blocking, la variable qu'elle nomme (ou null), et la section qu'elle cible ({id, title, kind}, ou null pour une anomalie qui porte sur tout le document). |
| sanitisation | Une simulation de l'assainisseur de contenu, une entrée par fragment que vous transmettez dans le corps de la requête (rien n'est enregistré). |
| stored | Des constats sur le contenu déjà enregistré : tokens inertes, images inaccessibles, bandes de titre courant tronquées, variables inutilisées, tableaux de mise en page non standard, la palette utilisée, l'usage des sauts de page, et la typographie (tailles et graisses réellement utilisées, et celles qu'aucune famille ne porte). |
Pour simuler un contenu avant de l'enregistrer, envoyez des fragments :
curl https://app.doclift.io/api/v1/workflows/templates/100050/validate \
--request POST \
--header "X-Api-Key: <your-api-key>" \
--header "Content-Type: application/json" \
--data '{
"content": ["<p onclick=\"x()\">Hello <variable>investor_name</variable></p>"],
"scope": "content"
}'
{
"scope": "content",
"given": "<p onclick=\"x()\">Hello <variable>investor_name</variable></p>",
"sanitised": "<p>Hello <variable>investor_name</variable></p>",
"removed_tags": [],
"removed_attributes": ["onclick"],
"unknown_references": [],
"inert_tokens": [],
"unreachable_images": [],
"ejected_from_paragraph": [],
"removed_css_declarations": [],
"clean": false
}
clean vaut false dès que l'un de removed_tags, removed_attributes,
inert_tokens, unreachable_images, ejected_from_paragraph, ou
removed_css_declarations est non vide : c'est le seul endroit qui vous
dit qu'un enregistrement perdrait quelque chose, avant même de l'enregistrer.
Voir Les échecs qui répondent 200 pour ce que
chacun de ces champs attrape réellement.
content, s'il est présent, doit être un tableau de strings ; scope
(content ou running_title) choisit quel assainisseur s'exécute.
Chacune de ces deux erreurs répond 422 avant que quoi que ce soit
d'autre ne s'exécute :
| Échec | Statut |
|---|---|
| content | 422 |
| scope | 422 |
Types d'anomalies
Six types bloquent la publication ; trois sont non bloquants et ne le font jamais.
| Type bloquant | Signification |
|---|---|
| broken_reference | Un token, une condition, un placement, une bande, un repeat_over, ou un data-loop nomme une variable ou un champ de ligne qui n'existe pas. |
| out_of_loop_reference | Un collection.field qualifié est cité là où aucune boucle de lignes ne met cette collection dans le périmètre. |
| nested_row_loop | Un data-loop se trouve à l'intérieur d'un nœud qui répète déjà, ou à l'intérieur de la propre ligne d'une autre boucle. |
| collection_comparison | Le nom propre d'une variable collection est comparé avec un opérateur autre que present/blank. |
| contradiction | Une condition qu'aucun payload ne peut jamais satisfaire (par exemple la même variable devant valoir deux choses différentes à la fois). Signalée une seule fois, sur l'ancêtre le plus haut où la contradiction tient. |
| empty_document | L'arborescence n'a aucun nœud rich_content ni image_with_variable : seulement des groupes, ou rien. Ne cible aucune section. |
| Type non bloquant | Signification |
|---|---|
| missing_background | Une section image_with_variable n'a pas encore d'image définie. |
| empty_membership | Une règle in/not_in a une liste values vide : elle ne décide rien à elle seule. |
| optional_conditioning | Une condition repose sur une variable qui n'est pas required, si bien qu'un oubli d'un auteur peut silencieusement raccourcir le document. |
Le contrat de payload
Lecture seule, aucun corps. Renvoie exactement les variables dont un payload de génération pour ce workflow a besoin, plus un exemple prêt à envoyer.
curl https://app.doclift.io/api/v1/workflows/templates/100050/payload_contract \
--header "X-Api-Key: <your-api-key>"
{
"variables": [
{
"name": "investor_name",
"description": "Full legal name",
"required": true,
"field_type": "text",
"allowed_values": [],
"seed_value": "Jane Doe",
"fields": null
}
],
"required": ["investor_name"],
"collections": ["investments"],
"limits": { "collection_rows": 200 },
"example": {
"document_request": {
"document_generations": [
{
"template_id": 100050,
"variables": {
"investor_name": "Jane Doe",
"investments": [{ "product": "SCPI", "amount": "10 000 €" }]
},
"tag": ""
}
],
"tag": ""
}
}
}
example est un payload réel et satisfaisant : chaque variable déclarée
présente, initialisée depuis son seed_value quand elle en a une, chaque
collection rendue comme un tableau de lignes plates utilisant ses noms de
champs déclarés. Copiez-le dans
POST /api/v1/document_requests et attendez-vous à ce qu'il réussisse,
sans avoir à deviner les formes. Voir
Modèles workflow pour la façon dont
cet endpoint impose le contrat de variables requises que cet exemple
satisfait déjà.
Publier et dépublier
curl https://app.doclift.io/api/v1/workflows/templates/100050/publication \
--request POST \
--header "X-Api-Key: <your-api-key>"
Exécute le même contrôle d'intégrité que validate, contre la même
arborescence enregistrée. Si une anomalie bloquante subsiste, la
publication est refusée et le corps de la réponse les liste toutes, pas
seulement la première :
{
"error": "<message>",
"anomalies": [
{ "type": "broken_reference", "section_id": 8823, "variable": "investor_name" }
]
}
Sinon :
{ "published": true }
Les anomalies non bloquantes ne bloquent jamais cet appel : un workflow
avec un missing_background ou un empty_membership se publie sans
problème. 409 si le verrou d'édition du constructeur est détenu.
curl https://app.doclift.io/api/v1/workflows/templates/100050/publication \
--request DELETE \
--header "X-Api-Key: <your-api-key>"
204 No Content. Le retrait n'est jamais soumis à l'intégrité. Un
workflow dont les références se sont cassées après sa publication peut
tout de même être retiré, volontairement : c'est exactement celui qui
doit pouvoir l'être. Toujours 409 si le verrou d'édition est détenu.
Un workflow publié est ce qui le rend éligible à la
génération de documents : seul un
workflow publié peut être ciblé par
POST /api/v1/document_requests.
La boucle
- 1
POST .../validate: lisezpublishableetanomalies. - 2Corrigez chaque anomalie bloquante que nomme la réponse. Les non bloquantes sont à vous d'agir ou de laisser.
- 3
POST .../validatede nouveau pour confirmerpublishable: true. - 4
POST .../publication. Un422ici signifie que l'étape 3 a manqué quelque chose. Le corps de la réponse liste exactement quoi.
Les anomalies ne bloquent jamais l'écriture d'une section ou d'une
variable ; elles ne bloquent que la publication. Vous pouvez enregistrer
une référence cassée, continuer d'éditer, et ne le découvrir qu'au moment
de validate ou de publication. Voir
Les échecs qui répondent 200 pour les échecs
qui n'atteignent même pas ce stade.