Aller au contenu

Modèles, rôles et champs

Un modèle est un contrat réutilisable. Il possède un nom, un unique brouillon et un nombre quelconque de versions publiées. Les enveloppes sont toujours créées à partir d’une version publiée, qui est immuable : modifier un modèle revient à enregistrer un nouveau brouillon et à le publier comme version suivante. Les enveloppes déjà envoyées conservent la version qu’elles ont figée.

GET /v1/templates/tpl_…
{
"id": "tpl_3kQ9xV2mLp",
"organization": "org_…",
"name": "Mutual NDA",
"description": "Two-party NDA, US law",
"latestVersion": 3,
"draftVersion": 4,
"createdAt": "2026-10-01T09:12:44.120Z",
"updatedAt": "2026-10-12T16:03:10.981Z"
}

Les identifiants sont des chaînes préfixées (tpl_, tplv_, tfl_, env_, rcp_, ses_, lnk_, evt_, whk_, whd_, …) ; les horodatages sont au format RFC 3339, en UTC.

Le mode Superposition (source: "pdf") part d’un document importé. Les champs sont des rectangles placés sur ses pages, exprimés en points PDF (1/72 de pouce), avec l’origine en haut à gauche de la page et un index de page commençant à 0. Un fichier .docx importé est converti une fois en PDF (avec LibreOffice, en conservant la mise en page Word ; les polices non incorporées au fichier peuvent être remplacées), puis il devient un PDF comme un autre : le fichier indique convertedFrom: "docx". Les versions en mode Superposition peuvent aussi comporter des modifications de contenu (texte modifié sur place, masquage, zones de texte, images, opérations sur les pages), appliquées à la publication de la version.

Le mode Document (source: "document") stocke le contrat lui-même en texte enrichi (JSON ProseMirror), avec des puces de variables comme {{client.name}}, des blocs de champs en ligne, des sections conditionnelles (conservées uniquement lorsqu’une expression showIf est vraie) et des sections et lignes de tableau répétées (une par élément d’une variable de type tableau). Chaque enveloppe génère son propre PDF, et la position des champs est lue à partir de ce rendu. Dans le tableau de bord, le mode Document correspond à « Partir d’un document vierge ». Via l’API, un fichier Word peut aussi être importé en mode Document avec POST /v1/templates/{id}/import : les {{tags}} deviennent des variables ou des champs, et les lignes de signature (« Signature: ____ », « By: ____ », « Date: ____ ») deviennent des blocs de champs.

Nouveau modèle propose deux points de départ :

  • Importer un document : une zone de dépôt pour les fichiers .pdf et .docx jusqu’à 25 Mo. Les fichiers Word sont convertis en PDF et s’ouvrent dans l’éditeur avec un rappel invitant à vérifier la mise en page convertie avant de placer les champs. Les petites corrections se font directement sur le PDF (« Modifier le contenu ») ; pour une réécriture plus importante, modifiez le fichier Word et importez-le à nouveau.
  • Partir d’un document vierge : rédigez le contrat en mode Document.

Le mode Modifier le contenu de l’éditeur change ce que voient les signataires sans toucher au fichier importé. Son outil par défaut, Modifier le texte, met en évidence les blocs de texte de la page (lignes et paragraphes regroupés à partir de la couche de texte du PDF) ; cliquez sur un bloc, ou atteignez-le avec Tab et appuyez sur Entrée, pour le modifier sur place, à la même position, dans la même taille, la même couleur, le même alignement et la même police. Ctrl/Cmd+Entrée enregistre, Échap annule, et chaque modification peut être rétablie depuis la liste des modifications. Les modifications s’annulent comme n’importe quel autre changement. Les autres outils ajoutent des masquages, des zones de texte et des images, et permettent d’insérer, de supprimer, de réordonner ou de faire pivoter des pages.

Une modification de texte sur place est stockée sous forme de deux éléments partageant un même group : un masquage recouvrant le bloc d’origine (dans la couleur de fond de la page) et un élément de texte disposé dans le bloc, avec l’interligne et la première ligne de base du bloc :

edits.items (excerpt)
[
{ "id": "whiteout_k2", "kind": "whiteout", "group": "blk_k1", "page": 0, "color": "#FFFFFF",
"rect": { "x": 71, "y": 209.9, "width": 452, "height": 26.9 } },
{ "id": "text_k3", "kind": "text", "group": "blk_k1", "page": 0, "rect": { "x": 72, "y": 210.9, "width": 451, "height": 24.9 },
"text": "1. Purpose. The Parties wish to evaluate a joint venture…", "original": "1. Purpose. The Parties wish to evaluate a possible business relationship…",
"size": 10.5, "lineHeight": 15.23, "baseline": 7.54, "padding": 0, "align": "left", "color": "#0B0F1A",
"face": { "source": "pdf", "name": "ABCDEF+Calibri", "fallback": "carlito" }, "font": "helvetica" }
]

face choisit la police : la police incorporée au PDF lorsqu’elle peut afficher tous les caractères du nouveau texte, sinon une police fournie aux métriques compatibles (sans Arimo pour Helvetica/Arial, serif Tinos pour Times, mono Cousine pour Courier, carlito Carlito pour Calibri) dans la graisse et le style correspondants. Le texte est renvoyé à la ligne à l’intérieur du bloc ; s’il lui faut plus de lignes que l’original, la modification s’étend dans l’espace libre en dessous, et l’éditeur refuse de l’enregistrer s’il n’y en a pas (« le texte ne tient pas — raccourcissez-le ou ajoutez de l’espace »). L’éditeur et l’API partagent le même code de mise en page et de polices : le PDF publié correspond donc ligne pour ligne à l’aperçu.

Les modifications ne peuvent porter que sur un brouillon. La publication les applique à un nouveau PDF de base dont le SHA-256 est le documentHash de la version (le hachage de ce que voient les signataires) ; l’original importé est conservé comme sourceFile de la version, et le brouillon suivant repart de celui-ci avec les mêmes modifications. Un masquage ne cache le contenu que visuellement ; le texte d’origine reste présent en dessous dans le fichier : ce n’est donc pas un caviardage sécurisé.

Les rôles sont les parties au contrat. Les destinataires d’une enveloppe sont associés aux rôles par leur key.

{ "key": "client", "label": "Client", "kind": "signer", "order": 1, "verification": "none" }
Propriété Signification
key Identifiant en minuscules (^[a-z][a-z0-9_]*$) utilisé par les champs et par les destinataires des enveloppes
kind signer (doit avoir un champ de signature ou d’initiales), approver, form_filler ou cc (reçoit, ne signe jamais)
order Ordre d’acheminement à partir de 1. Les rôles de même ordre signent en parallèle ; l’ordre suivant commence lorsqu’ils ont terminé
verification La façon dont le destinataire du rôle prouve son identité : none (par défaut : le lien de signature unique seul) ou email_otp (le lien plus un code envoyé par e-mail). Un destinataire peut la remplacer ; consultez Vérification du signataire

passkey, id_check et sms_otp figurent dans le schéma, mais ne sont pas encore disponibles pour la signature : un modèle qui utilise passkey ou id_check ne peut pas être publié, et les codes SMS ne sont pas encore envoyés.

{
"id": "client_signature",
"type": "signature",
"role": "client",
"label": "Signature",
"required": true,
"rect": { "page": 1, "x": 72, "y": 610, "width": 220, "height": 48 }
}

Types de champs : signature, initials, name, email, date_signed, text, number, date, checkbox, radio, dropdown, attachment, formula, stamp et variable_text (rempli à partir d’une variable par l’expéditeur, et non par un signataire). Les champs peuvent également comporter :

  • variable : un JSON Pointer vers les variables (/client/name) pour lier ou préremplir le champ ;
  • options pour radio et dropdown ;
  • validation : pattern, min, max, maxLength ou un format (email, phone, date, number, currency) ;
  • showIf : une condition portant sur les variables et d’autres champs, par exemple plan != "free" ;
  • formula : une valeur calculée, en lecture seule ;
  • overflow : le comportement lorsqu’une valeur ne tient pas dans la zone : shrink (par défaut), wrap ou reject.

Les variables d’une version sont un JSON Schema (draft 2020-12) décrivant les données que vous envoyez avec chaque enveloppe ; les sampleVariables de la version en donnent un exemple. POST /v1/envelopes valide vos variables par rapport à ce schéma et signale chaque problème avec un JSON Pointer :

{
"type": "https://bonafidesign.com/problems/validation-error",
"title": "Validation failed",
"status": 422,
"detail": "The request is invalid.",
"errors": [
{ "pointer": "/variables/client/name", "message": "is required", "hint": "Provide a value for 'name'." }
]
}

Pour voir le résultat avant l’envoi, générez un aperçu filigrané de n’importe quelle version avec POST /v1/templates/{id}/versions/{version}/render ({ "variables": { … } } → PDF), ou créez l’enveloppe avec ?dry_run=true.

La plupart des équipes conçoivent leurs modèles dans l’éditeur du tableau de bord. Tout ce qu’il fait est disponible via l’API :

  1. POST /v1/templates avec { "name": "Mutual NDA" }.
  2. POST /v1/templates/{id}/files avec le PDF (ou le .docx) comme corps (Content-Type: application/pdf) ou comme champ multipart file. Jusqu’à 25 Mo. La réponse contient l’identifiant du fichier (tfl_…), le nombre de pages et leurs dimensions.
  3. PUT /v1/templates/{id}/draft avec roles, fields, variables (et file, ou source: "document" avec content). Les brouillons sont enregistrés tels quels ; rien n’est encore vérifié.
  4. POST /v1/templates/{id}/publish. La publication contrôle le brouillon : le rôle de chaque champ existe, chaque rôle de signataire a un champ de signature, les champs tiennent dans leurs pages, les champs radio et liste déroulante ont des options, les expressions sont analysables. Les problèmes sont renvoyés sous forme de 422 avec des pointeurs tels que /fields/3/rect.
Fenêtre de terminal
curl https://api.bonafidesign.com/v1/templates/tpl_3kQ9xV2mLp/files \
-H "Authorization: Bearer $BONA_FIDE_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @nda.pdf

Les endpoints de version acceptent un numéro, latest ou draft : GET /v1/templates/{id}/versions/latest, GET /v1/templates/{id}/versions/2/document (le PDF de base). Un modèle qui n’a jamais été utilisé par une enveloppe ni par un lien de signature peut être supprimé ; sinon, DELETE répond 409 in-use.