Workflows

Workflows

API v115 août 2026·9 min de lecture

Ce qu'est un workflow Doclift, son modèle objet, et l'ordre exact pour en construire un : des capabilities jusqu'au document généré.

Ce qu'est un workflow

Un workflow est un modèle category: "workflow" construit à partir d'une arborescence de sections plutôt que d'un corps HTML unique. Un modèle personnalisé est un seul bloc de balisage écrit à la main ; un formulaire à remplir tire ses variables des champs d'un PDF importé. Un workflow n'a lui-même aucune colonne content : ce qui se rend est la concaténation des sections que les conditions de votre payload de génération laissent visibles. Il possède sa propre surface de création, entièrement sous /api/v1/workflows/* ; les endpoints d'écriture classiques de /api/v1/templates ne le touchent jamais, et ne le lisent qu'une fois publié (voir Types de modèles).

Bêta privée

Les workflows sont en bêta privée : non activés par défaut, l'accès est accordé sur demande. Écrivez à [email protected] pour en faire la demande. Comme pour toute bêta, cette surface est encore susceptible d'évoluer.

Ce que le workflow vous apporte par rapport aux deux autres familles, c'est la structure : des groupes imbriqués, chacun avec sa propre condition, contenant des sections de contenu qui s'impriment ou non selon ce que l'appelant envoie. C'est aussi toute la raison pour laquelle il compte une trentaine d'endpoints là où un modèle personnalisé n'en a que quatre : chaque élément de cette structure (un groupe, une condition, un placement sur une image, une surcharge de thème) est lui-même une chose adressable.


Le modèle objet

  • Modèle de workflow : la ligne Template elle-même. Elle porte les mêmes title, description, orientation et quatre champs margin_* que n'importe quel autre modèle, plus published. Elle possède tout ce qui suit : sections, variables, jeux de données, images et un thème.
  • Sections : l'arborescence. Un nœud est soit un groupe (un titre, une condition optionnelle, et des enfants ; jamais de contenu propre), soit une section de contenu qui porte du contenu ou des placements mais jamais d'enfants. L'arborescence compte trois niveaux au maximum : « groupe, groupe, section ». La liste des kind de section n'est pas figée dans cette documentation : lisez section.kinds depuis GET .../capabilities au moment de l'exécution ; voir Sections pour la forme que porte chaque kind.
  • Variables : déclarées une fois, citées par leur nom depuis les conditions, les tokens et les placements, sans clé étrangère : supprimer ou renommer une variable ne se répercute jamais dans les sections qui la citent. La référence survit, cassée, et n'est signalée qu'à la prochaine validation ou publication, jamais balayée silencieusement. Une variable collection déclare en plus les champs d'une ligne ; ses lignes sont adressées comme collection.field dans l'arborescence, et collection.i.field une fois développées à l'intérieur d'une section répétée.
  • Jeux de données : des cartes nom → valeur plates et nommées, que vous enregistrez pour prévisualiser le workflow. La forme d'un jeu de données est identique à celle d'un vrai payload de génération (un jeu que vous pouvez prévisualiser est un payload que vous pouvez rejouer sur POST /api/v1/document_requests sans le remanier).
  • Images : des images importées via l'API workflow et citées depuis le contenu d'une section par l'URL que renvoie l'import, par opposition aux arrière-plans, qui sont attachés directement à une section image_with_variable plutôt que d'exister comme leur propre ressource. Les deux comptent pour la même raison : le moteur de rendu n'émet aucune requête réseau en produisant un PDF, donc une image citée par n'importe quelle autre URL s'imprime comme un cadre vide, silencieusement, la génération répondant tout de même un succès. Chaque image doit d'abord passer par cette API.
  • Thème, les valeurs typographiques par défaut du document : quatre types de blocs (paragraph, h1, h2, h3) croisés avec quatre propriétés modifiables (font_family, font_size, color, line_height). Il voyage à l'intérieur de chaque instantané publié, donc un document déjà publié continue de se rendre comme il se rendait le jour de sa publication, même si le thème est modifié ensuite.

Capabilities fait foi, ce n'est pas une copie

GET /api/v1/workflows/capabilities est le seul endroit où chaque valeur ci-dessous est déclarée, et il doit être lu au moment de la requête : ne jamais le recopier dans un client ou un script comme une liste figée. Trois groupes de valeurs qu'il renvoie sont des réglages propres à l'organisation, pas des constantes produit :

ValeurFondée surDéfaut
limits.sectionsle plafond de sections propre à l'organisation200
limits.image_bytesle plafond de taille d'image propre à l'organisation10 Mo
limits.document_lengthle plafond de taille rendue propre à l'organisation800 000 caractères

Le back-office d'une organisation peut relever ou abaisser chacun de ces trois plafonds indépendamment des autres ; un document qui affiche « 200 sections » comme un fait produit décrit en réalité le réglage actuel d'un client, pas une limite de l'API. Deux autres groupes dépendent du déploiement en cours plutôt que de l'organisation, et peuvent changer au fil d'un déploiement : les listes blanches de l'assainisseur (content.allowed_tags, content.allowed_attributes) et le catalogue de polices (authoring.fonts, theme.font_size, theme.fonts) sont tous deux lus depuis l'application en cours d'exécution à chaque appel plutôt que figés au démarrage, car ce qu'ils renvoient évolue indépendamment du code qui les lit.

Tout le reste que capabilities renvoie (kind de section, opérateurs de condition, clés de placement, géométrie de page, types d'anomalies) est une véritable constante produit, stable. Lisez-la quand même en direct : l'endpoint porte quelques enrichissements qui n'existent qu'au moment de l'appel, et un client qui suppose une forme statique est exactement la classe de bug que cet endpoint existe pour prévenir. Voir Récupérer les capabilities pour la réponse complète.


L'erreur la plus coûteuse : figer une valeur hors du thème

Rien dans la forme de l'API ne le révèle, et rien ne le signale après coup : écrire un contenu qui déclare en ligne exactement ce que le thème dit déjà ressemble, aujourd'hui, à laisser la valeur héritée. Un paragraphe dont le thème indique 12 pt Arial, écrit avec un font-size: 12pt en ligne sur le même élément, rend le même PDF à l'instant présent. La différence n'apparaît que la prochaine fois que quelqu'un change le thème : le paragraphe simple le suit, celui qui porte la valeur en ligne identique ne le suit pas, pour toujours, parce que rien dans PATCH .../theme ni dans le contenu d'une section ne regarde jamais ce que l'autre a déclaré. Il n'existe aucun type d'anomalie pour cela, aucun champ dans la réponse de validate : c'est une discipline de modélisation, pas une règle vérifiée. Réglez le thème avant d'écrire le contenu des sections, et laissez les sections en hériter plutôt que de le répéter.


Construire un workflow de bout en bout

Voici l'ordre qui vous mène à un document sans détour par une référence cassée découverte trop tard. Pour chaque étape, la note précise si l'API vous empêche de la sauter, ou si la sauter se contente d'enregistrer proprement pour échouer plus tard.

  1. 1Lisez GET .../capabilities, une fois par session. Rien ne l'impose ; tout ce qui suit doit être vérifié contre cette réponse en direct, jamais contre une hypothèse codée en dur.
  2. 2Créez le modèle : POST .../templates avec title et description ; orientation et les quatre marges peuvent suivre par PATCH. Vous avez besoin de l'id de cette étape avant que tout le reste puisse exister, elle vient donc en premier par nécessité.
  3. 3Créez chaque variable, un appel par variable, avant que le moindre contenu n'en cite une. Non imposé : il n'existe aucune clé étrangère d'une condition ou d'un token vers une variable, donc écrire le contenu en premier réussit et vous laisse une référence cassée à trouver plus tard, à validate ou à la publication.
  4. 4Réglez le thème (PATCH .../theme) avant d'écrire le contenu des sections. Non imposé par aucune écriture, mais voir l'erreur du gel ci-dessus : le faire une fois que le contenu existe déjà, c'est exactement ainsi qu'une section finit par porter une valeur en ligne qui cesse silencieusement de suivre le thème.
  5. 5Créez les sections, de haut en bas : un groupe (avec toute sa sous-arborescence passée en children) ou une feuille à la fois, en renseignant les backgrounds (PATCH .../sections/:id/background) et les images de contenu riche (POST .../images, puis en citant l'URL renvoyée) au fur et à mesure. L'ordre parent-avant-enfant est imposé pour un parent_id que vous nommez vous-même (un parent inconnu est refusé), mais toute une sous-arborescence créée en un seul appel contourne la question entièrement.
  6. 6Validez (POST .../templates/:id/validate) avant de publier, et de nouveau après toute modification importante. Non imposé comme précondition : les anomalies répondent toujours 200 et ne bloquent jamais un enregistrement à elles seules ; seule la publication bloque sur les six types bloquants. Exécuter cette étape en premier ne fait que vous éviter de deviner laquelle a déclenché le blocage.
  7. 7Publiez : POST .../templates/:id/publication. Imposé : refusé avec 422 tant qu'une anomalie bloquante subsiste, et le corps de la réponse les liste toutes.
  8. 8Générez : POST /api/v1/document_requests en nommant ce workflow comme template_id. Imposé : seul un workflow publié peut être généré ; voir API Document requests.
  9. 9Lisez le document réel. Rien dans cette API ne compare le PDF rendu à l'intention qui le sous-tend. C'est la seule étape qui rattrape tout ce que les autres ne peuvent pas.

Un appelant peut créer sections, variables et jeux de données dans n'importe quel ordre que la couche HTTP autorise : aucune des étapes 3 à 5 n'est imposée comme précondition par une quelconque validation. L'ordre ci-dessus est un conseil contre un mode d'échec précis et sinon silencieux, pas une machine à états que l'API elle-même impose.


Suite