Créer le workflow
Créer le workflow
Parapheurs (workflows)
Qu’est-ce qu’un parapheur ?
Un parapheur (workflow) est un processus de signature et/ou de validation. Il est
créé sous un utilisateur — son gestionnaire — et porte un identifiant wfl_.
Un parapheur est composé d’étapes (steps), jouées séquentiellement. Chaque étape réunit un ou plusieurs destinataires (recipients) qui agissent, eux, en parallèle. C’est la combinaison des deux qui décrit l’ordre des signatures :
- plusieurs destinataires dans une même étape → ils signent/valident en parallèle ;
- plusieurs étapes successives → elles s’enchaînent dans l’ordre (séquentiel).
Structure d’ensemble — chaque niveau porte ses propres champs :
Deux modes existent :
FULL(par défaut) — toutes les possibilités : plusieurs étapes, observateurs, consolidation, création depuis un modèle…SINGLE_SIGNER— un parapheur à une seule étape (le plus simple).
Remarque importante : le mode SINGLE_SIGNER (“signataire unique”) permet en particulier de construire un parapheur avec des champs dynamiques qui sont à compléter par le signataire avant la signature. Cette fonctionnalité est prise en charge par le Workflow Manager mais pas par l’Evidence Manager et donc le processus de saisie de ces informations n’est pas géré par le fichier de preuve.
Du fait que son intérêt est surtout de permettre à un gestionnaire de parapheur d’autoriser une saisie préalable afin de faire compléter un ou plusieurs documents par le signataire avant sa signature, il est important de noter que dès lors qu’un développeur s’appuie sur l’API, il est préférable de faire effectuer cette saisie ainsi que tous ses contrôles associés par l’application métier. À noter d’ailleurs qu’aucun contrôle n’est effectué par le Workflow Manager sur les champs de saisie qui sont uniquement du texte libre. Par conséquent le mode SINGLE_SIGNER n’est pas abordé plus avant dans cette documentation. On précise également que le mode signataire unique peut être désactivé au niveau du tenant.
Créer un parapheur (à l’état brouillon)
Le parapheur est rattaché au gestionnaire ({userId} dans l’URL) et créé à l’état
brouillon : rien n’est envoyé tant qu’il n’est pas lancé (section Cycle de vie & statuts). L’appel s’authentifie
avec un jeton d’API dont l’utilisateur a le droit de créer des parapheurs (fondation Groupes, rôles & droits).
Le corps reflète les niveaux ci-dessus : les champs propres du parapheur, le tableau steps[]
(chaque étape contenant ses recipients[]) et, le cas échéant, watchers[]. Les quatre
sections suivantes détaillent chacun de ces niveaux.
Le parapheur — champs de premier niveau (niveau 1)
Cogestion. La possibilité de faire cogérer un parapheur par d’autres utilisateurs (champs
allowedCoManagerUsers/coManagerNotifiedEventsvisibles sur l’objet parapheur) dépend entièrement des modèles : elle n’est disponible que pour un parapheur créé à partir d’un modèle. Les modèles étant hors périmètre d’une utilisation raisonnée de l’API (voirtemplateIdci-dessus et la fondation Positionnement et périmètre), la cogestion n’est donc pas détaillée ici.
Les étapes — steps (niveau 2)
Les étapes s’enchaînent séquentiellement. Champs propres à chaque étape :
(Toutes les durées sont en millisecondes — fondation Structure > Formats de données.)
Les destinataires — recipients (niveau 3)
Les destinataires d’une même étape agissent en parallèle. Chaque destinataire est
associé à une page de consentement (consentPageId), qui fixe le choix d’un cachet ou
d’une signature des documents et le mode d’authentification du destinataire (fondation Pages de consentement).
On l’identifie de l’une des manières suivantes :
- par
userId— le destinataire est un utilisateur (recommandé : son identité est reprise de sa fiche, fondation Provisionnement des utilisateurs) ; - par
contactId— le destinataire est un contact (fondation Provisionnement des utilisateurs > Contacts : des signataires privés à un utilisateur) ; - par identité en clair —
email+firstName+lastName.
Contrairement au comportement du portail, qui permet de créer « à la volée » utilisateurs et/ou contacts lors de la création d’un parapheur, avec l’API, les utilisateurs et/ou contacts désignés doivent exister au préalable : l’API ne les crée pas automatiquement. L’identité en clair reste utilisable, mais elle produit un destinataire ad hoc, propre à ce parapheur : il n’est pas enregistré comme utilisateur ou contact réutilisable. Le détail des règles d’identification (et pourquoi
userIdest préférable) est traité dans les cas d’usage.
Autres champs propres au destinataire, utiles voire indispensables :
Les observateurs — watchers (niveau 4) & les notifications
Deux mécanismes de notification, tous deux au niveau du parapheur :
notifiedEvents— la liste des événements dont le gestionnaire est notifié.watchers— des observateurs supplémentaires, chacun avec ses propresnotifiedEvents. (Null enSINGLE_SIGNER.) Chaque observateur est soit un utilisateur (watchers[].userId), soit un non-utilisateur désigné par son e-mail (watchers[].email). Côté Portail, cela correspond aux deux boutons « Ajouter un observateur » (liste déroulante des utilisateurs →userId) et « Ajouter un CC » (liste déroulante des contacts du gestionnaire, ou une adresse e-mail saisie librement). Dans tous les cas, un CC arrive à l’API sous la forme d’un e-mail (watchers[].email) : le champcontactIdn’est pas pris en charge pour un watcher (il est ignoré silencieusement, l’observateur n’étant alors pas enregistré).
Les valeurs de notifiedEvents (mêmes valeurs pour le gestionnaire et pour chaque observateur) sont les suivantes :
workflowStarted: le parapheur est démarré ;recipientFinished: un destinataire a signé ou validé ;recipientRefused: un destinataire a refusé de signer ou de valider ;workflowStopped: le parapheur est arrêté ;workflowFinished: le parapheur est terminé ;workflowFinishedDownloadLink: le parapheur est terminé et un lien de téléchargement des fichiers signés avec les pièces jointes a été envoyé ;workflowFinishedDownloadLinkNoAttachment: le parapheur est terminé et un lien de téléchargement des fichiers signés sans les pièces jointes à été envoyé ;commentCreated: un commentaire a été déposé (les commentaires peuvent être désactivés au niveau du tenant) ;coManagerAdded: un cogestionnaire a été ajouté au parapheur (s’appuie sur les modèles) ;coManagerRemoved: un cogestionnaire a été retiré du parapheur (s’appuie sur les modèles).
Ce sont les mêmes eventTypes que les webhooks ; la liste exhaustive et la charge utile sont traitées dans la fondation Suivi & webhooks.
Minimiser les e-mails. Pour ne laisser au signataire que l’invitation à signer :
- mettez
notifiedEvents: []au niveau du parapheur → aucune notification e-mail au gestionnaire (ni « un destinataire a signé », ni « parapheur terminé », etc.) ;- n’ajoutez aucun
watchers(personne en copie/observateur) ;- laissez
sendDownloadLink: falseau niveau de l’étape → pas d’e-mail de lien de téléchargement du document signé en fin de parapheur.L’invitation du signataire est, elle, indépendante de
notifiedEvents: elle part au lancement et se règle viainvitePeriod/maxInvites(section Les étapes — steps (niveau 2)). Pour une invitation unique, sans relance, mettezmaxInvites: 1.
Cycle de vie & statuts
Le statut d’un parapheur est porté par workflowStatus. Les valeurs effectivement renvoyées
par l’API sont :
Deux pièges de vocabulaire à connaître.
- Le Portail affiche « Clôturé », mais la valeur du champ utilisé en mode API est
archived(pour raisons historiques : ce statut, d’abord nommé « Archivé », a été renommé « Clôturé » côté Portail lors de l’ajout des connecteurs d’archivage, sans changer la valeur de l’API).closedn’est pas un statut : c’est un horodatage (date de clôture). Le statut d’un parapheur clôturé est bienarchived.
Les transitions draft → started → stopped se font par PATCH /api/workflows/{id} avec
{ "workflowStatus": … } (concurrence optimiste If-Match facultative, fondation Structure > Concurrence : l’en-tête conditionnel If-Match) :
- Lancer —
draft→started: la première étape démarre, les premières invitations partent. - Arrêter —
started→stopped. - Reprendre un cycle — un parapheur
finishedoustoppedpeut être modifié (par exemple pour ajouter des étapes) puis redémarré.finishedn’est donc pas définitif. - Clôturer (
finished→archived) — c’est le seul état définitif (le parapheur est figé). La clôture ne se fait pas parPATCH workflowStatusmais par l’endpoint dédiéPOST /api/workflows/{id}/archive:
- archivage local (par défaut) : l’appel suffit ; les documents sont conservés localement dans l’environnement du Workflow Manager ;
- archivage externe (optionnel) : dépose les documents chez un tiers ; nécessite un
archiveur déclaré et l’activation sur le tenant (voir
activateExternalArchive+externalArchivingParameters), l’avancement étant suivi viaexternalArchiveStatus.
La clôture renseigne l’horodatage closed et conditionne la disponibilité définitive du dossier de preuve (voir la fondation Documents signés & preuves).
Horodatages : created, started, stopped, finished, closed.
Suivi en cours de déroulé : progress, steps[].isStarted / steps[].isFinished, currentRecipientEmails / currentRecipientUsers (qui doit agir maintenant).
Invitations à signer. L’invitation part automatiquement : au lancement du parapheur (
workflowStatus: started) et à la fin de chaque étape intermédiaire. Dans le cas normal, vous n’avez donc rien à appeler ; les relances sont réglées parinvitePeriod/maxInvites(section Les étapes — steps (niveau 2)). Deux endpoints permettent d’intervenir sur l’invitation —POST /api/workflows/{id}/invite(obtenir le lien) etPOST /api/workflows/{id}/sendInvite(renvoyer le message de la plateforme) — mais ils répondent à des besoins distincts, détaillés juste après. Tous deux exigent un corps{ "recipientEmail": … }identifiant le destinataire et renvoient l’inviteUrl— omettre ce corps provoque une erreur HTTP 500. Leurs erreurs métier renseignent sur les conditions :InvalidWorkflowStatus(le statut du parapheur n’autorise pas l’opération, par exemple parce qu’un administrateur ou un cogestionnaire a clôturé le parapheur entre temps),WorkflowNotFound,RecipientNotFound, et — poursendInvite—InviteAlreadySent.
Deux endpoints, deux usages sans rapport entre eux.
POST /api/workflows/{id}/invite— obtenir le lien pour l’acheminer soi-même. L’appel fabrique l’invitation et restitue soninviteUrlsans qu’aucun message ne parte. Associé àmaxInvites: 0(section Les étapes — steps (niveau 2)), il donne à l’application le contrôle entier de l’acheminement : c’est le mode prévu pour qu’un intégrateur transmette lui-même le lien de signature, par son propre canal ou en l’affichant dans son interface.POST /api/workflows/{id}/sendInvite— relancer l’invitation de la plateforme. L’appel réexpédie le message d’invitation émis automatiquement, par exemple lorsqu’il s’est perdu ou a été supprimé avec les indésirables. C’est l’équivalent, côté API, du bouton de relance dont dispose le gestionnaire dans le Portail. Il suppose donc l’envoi automatique (maxInvites≥ 1) et n’a pas de sens dans un parcours où l’application gère elle-même le lien.
Le second n’est pas le prolongement du premier : le lien issu de /invite est géré par
l’intégrateur, et /sendInvite ne s’y applique pas.
Ce que contient l’inviteUrl. L’adresse est de la forme https://<plateforme>/invite?token=…,
où le jeton est un JWT dont la charge utile désigne le parcours : aud (toujours invite),
workflowId, stepId, userId, consentVersion et iat. Deux conséquences pratiques :
- aucune revendication
expn’y figure — la durée de validité n’est pas dans le lien mais arbitrée côté serveur par levalidityPeriodde l’étape et le statut du parapheur ; il est donc inutile d’espérer prolonger un accès en manipulant l’URL ; - le lien est un porteur : sa seule détention suffit à se présenter comme le signataire désigné. Il ne doit pas être journalisé, ni transiter par une URL de redirection, ni s’afficher ailleurs que derrière l’authentification de votre application. L’authentification exigée par la page de consentement reste, elle, entièrement en place — voir la fondation Règles d’intégration technico-juridiques.
La référence propose par ailleurs la duplication et la suppression d’un parapheur.

